分析
经典的字眼,要求最小值最大。考虑二分答案。如何判断合法性。对于二分出来的最小值。从左向右扫一次,在考虑 时,我们已经保证 是一个合法的区间了,所以只有向后加才有意义。所以遇到小于二分出来的数时,直接 这个区间 。用差分数组维护一下就好了,当操作次数大于 时是不合法答案,时间复杂度为 。
代码
#include<bits/stdc++.h> using namespace std; const int N = 1e5 + 10; #define LL int LL read() {LL x;scanf("%d",&x);return x;} LL A[N],C[N],n,m,w; bool check(LL x) { LL tot = 0;memset(C,0,sizeof(C)); for(int i = 1;i <= n;i++) { C[i] = C[i] + C[i-1]; if(A[i] + C[i] < x) { LL c = x-A[i]-C[i]; tot+=c;C[i]+=c; if(i+w <= n) C[i+w]-=c; if(tot > m) return false; } } return tot <= m; } int main() { n = read();m = read();w = read(); for(int i = 1;i <= n;i++) A[i] = read(); LL l = 1,r = (1<<30),ans = 0; while(l <= r) { LL mid = l + r >> 1; if(check(mid)) l = mid + 1,ans = max(ans,mid); else r = mid - 1; } printf("%d\n",ans); return 0; }