[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;
}
posted @ 2018-10-21 21:52  SWHsz  阅读(154)  评论(0编辑  收藏  举报