差分+二分
题意大概是对于一个序列,每次可以给某个长度为(W)的序列(+1),可以操作(m)次。问序列最小值的最大值是多少。
差分一下,每次二分到一个最小值的最大值就开始遍历整个数组,发现假如第(i)个数小于(mid),就令(i->i+m-1)上的值加到(mid)
#include <iostream>
#include <cstdio>
#include <cstring>
#define int long long
using namespace std;
const int N=100005;
int n,m,a[N],cf[N],ans,w;
bool ck(int x) {
int now=0,day=0;
for(int i=1;i<=n;i++) {
now+=cf[i];
if(now<x) day+=x-now,cf[i]+=x-now,cf[min(n+1,i+w)]-=x-now,now+=x-now;
if(day>m) return 0;
}
return 1;
}
signed main() {
scanf("%lld%lld%lld",&n,&m,&w);
for(int i=1;i<=n;i++) scanf("%lld",&a[i]),cf[i]=a[i]-a[i-1];
int l=0,r=1e18;
while(l<=r) {
int mid=l+r>>1;
if(ck(mid)) l=mid+1,ans=mid;
else r=mid-1;
for(int i=1;i<=n;i++) cf[i]=a[i]-a[i-1];
}
cout<<ans<<endl;
return 0;
}