[CodeForces]460C Present

差分+二分
题意大概是对于一个序列,每次可以给某个长度为(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;
}
原文地址:https://www.cnblogs.com/sdfzhsz/p/9827141.html