C. To Become Max
https://codeforces.com/problemset/problem/1856/C
题意:给定长度为n的数组a,现在可以执行k次操作,每次操作可以选择i∈[1, n - 1],并且a[i] <= a[i + 1],令a[i] = a[i] + 1。问k次操作后,数组a中数字最大的是多少。
思路:暴力+二分,从前往后依次考虑所有的i,在当前的a[i]可能的值域上进行二分,然后看k次操作能否满足后面的数让a[i]变为当前的可能值,只需要满足a[i] = x, a[i + 1] = x - 1, a[i + 2] = x - 2..而且必须至少出现一个数不需要进行任何变换就能满足条件,这是得以让这个数前面位置的数进行操作的前提。比如5 4 3 2 1, k = 100000,虽然有足够的操作次数,但是没有出现天然的不需要改变就满足条件的数。
总结:一开始的思路是倒着找,贪心,从j往前,看看最多能让数字加到多少。但是思路错了,比如
5 6
6 5 4 1 5,最优解应该是第一个数变成7,如果按照贪心的思路,那么操作6次,只能得到6 5 5 6 5
inline void solve() {
int n, k;
cin >> n >> k;
vector<int> a(n);
for (auto& x : a) {
cin >> x;
}
int ans = a[n - 1];
for (int i = 0; i < n - 1; ++i) {
int l = a[i];
int r = 2e8 + 1;
while (l < r) {
auto valid = [&](int i, int x) mutable{
int kk = k;
int now = x;
for (int j = i; j < n; ++j) {
if (a[j] < now) {
int need = now - a[j];
if (kk < need) {
return false;
}
kk -= need;
now --;
}
else {
return true;
}
}
return false;
};
int mid = (l + r + 1) >> 1;
if (valid(i,mid)) {
l = mid;
}
else {
r = mid - 1;
}
}
ans = max(ans, l);
}
cout << ans << '\n';
}

浙公网安备 33010602011771号