原题传送门
最小值最大当然是二分答案
然后
O
(
n
)
O(n)
O(n)扫,如果当前数未达到
m
i
d
mid
mid,就加到
m
i
d
mid
mid,并且这个数是作为区间左端点的
如何实现区间加法,差分数组就行了
Code:
#include <bits/stdc++.h>
#define maxn 1000010
#define LL long long
using namespace std;
LL a[maxn], d[maxn], n, m, w, ans;
inline int read(){
int s = 0, w = 1;
char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') w = -1;
for (; isdigit(c); c = getchar()) s = (s << 1) + (s << 3) + (c ^ 48);
return s * w;
}
bool check(LL mid){
int sum = m;
for (int i = 1; i <= n; ++i) d[i] = 0;
for (int i = 1; i <= n; ++i){
d[i] += d[i - 1];
if (a[i] + d[i] < mid){
int x = mid - a[i] - d[i];
if (x > sum) return 0;
sum -= x, d[i] += x, d[i + w] -= x;
}
}
return 1;
}
int main(){
n = read(), m = read(), w = read();
for (int i = 1; i <= n; ++i) a[i] = read();
LL l = 0, r = 2e9;
while (l <= r){
LL mid = (l + r) >> 1;
if (check(mid)) ans = mid, l = mid + 1; else r = mid - 1;
}
printf("%lld\n", ans);
return 0;
}