rt,与题解不同,我是先排序,然后把每个数朝 an 跳(分开考虑比 an 大还是小),然后让这个新数列极差最小。
如果极差 ≥x 怎么操作我认为都不会更优(但为什么,求证明或 hack),否则一定能跳到 0
表述可能不太清楚,建议也扫一眼代码
#include<queue>
#include<cstdio>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
#define pb push_back
using namespace std;
typedef long long ll;
typedef pair<ll, ll> PII;
template<typename T> inline void read(T &x){
x = 0;
bool F = 0;
char c = getchar();
for (;!isdigit(c);c = getchar()) if (c == '-') F = 1;
for (;isdigit(c);c = getchar()) x = (x<<1)+(x<<3)+(c^48);
if (F) x = -x;
}
template<typename T> inline void checkmax(T &a, const T &b){a = max(a, b);}
template<typename T> inline void checkmin(T &a, const T &b){a = min(a, b);}
const int N = 1e5+5;
PII val[N];
ll a[N], x;
int n;
inline ll cal_pos(ll val, ll y){
ll l = val, r = val;
while (1){
if (l<=y && y<=r) return 0;
if (y<l) return l-y;
l *= 2, r = 2*r+x;
}
return -1;
}
inline ll cal_neg(ll val, ll y){
ll l = val, r = val;
while (1){
if (l<=y && y<=r) return 0;
if (y<2*l) return r-y;
l *= 2, r = 2*r+x;
}
return -1;
}
inline ll cal(){ // 用 val 求出最终极差
ll ans = 1e18, Min = 1e18;
for (int i = n;i>=1;i--){ // 固定最大值在 a[i].first 取到
checkmin(ans, val[i].first-min(val[1].first, Min));
checkmin(Min, val[i].second);
}
return ans;
}
int main(){
read(n), read(x); for (int i = 1;i<=n;i++) read(a[i]); sort(a+1, a+n+1);
ll ans;
for (int i = 1;i<=n;i++){
val[i].first = cal_pos(a[i], a[n]); // 计算正的
val[i].second = cal_neg(a[i], a[n]); // 计算负的
}
sort(val+1, val+n+1);
ans = cal();
printf("%lld\n", ans >= x ? ans : 0);
return 0;
}