结论题,过但不解,求证
查看原帖
结论题,过但不解,求证
255436
wangsiyuanZP楼主2023/8/30 14:35

rt,与题解不同,我是先排序,然后把每个数朝 ana_n 跳(分开考虑比 ana_n 大还是小),然后让这个新数列极差最小。

如果极差 ≥x\ge x 怎么操作我认为都不会更优(但为什么,求证明或 hack),否则一定能跳到 00

表述可能不太清楚,建议也扫一眼代码

#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;
}
2023/8/30 14:35
加载中...