Present
题目大意:
先给你一串序列,你至多有次操作使得一段长度为的区间加一
问这串序列的最小值最大可以是多少?
分析:
最小值最大或者最大值最小,我们的第一反应可能都是二分答案
简单证明一下:
如果最小值最大为,那么只要我们少做一次操作,那么也是可行的
这满足二分答案的性质,所以呢二分答案没有问题的
那么关于函数的话,如果当前我们枚举到的数他小于这个我们的值,那么我们就给这一段区间加上这个差值(如果可以加,否则返回零)
那么时间复杂度大概就是,可以接受的
#include <bits/stdc++.h> using namespace std; typedef long long ll; const ll maxn = 1e5 + 10; const ll mod = 1e9 + 7; inline ll __read() { ll x(0), t(1); char o (getchar()); while (o < '0' || o > '9') { if (o == '-') t = -1; o = getchar(); } for (; o >= '0' && o <= '9'; o = getchar()) x = (x << 1) + (x << 3) + (o ^ 48); return x * t; } ll n, m, w, a[maxn]; ll CF[maxn], temp[maxn]; ll l(0x7fffffff), r, ans; inline bool Check(ll x) { memcpy(temp + 1, CF + 1, sizeof(ll) * n); ll now(0), rest(m); for (ll i = 1; i <= n; ++i) { now += temp[i]; if (now >= x) continue; if (now + rest < x) return 0; ll get = x - now; rest -= get; now += get; if (i + w <= n) temp[i + w] -= get; } return 1; } signed main() { n = __read(), m = __read(), w = __read(); for (ll i = 1; i <= n; ++i) { a[i] = __read(); CF[i] = a[i] - a[i - 1]; l = min(l, a[i]), r = max(r, a[i]); } r += m; while (l <= r) { ll mid = (l + r) >> 1; if (Check(mid)) ans = mid, l = mid + 1; else r = mid - 1; } printf ("%lld\n", ans); system("pause"); }