Codeforces 460C —— Present(二分答案)

题目:Present

题意:给定N朵花的原先的高度,从左到右排列,最多浇水m天,每天只能浇一次,每次使得连续的w朵花的高度增长1,问最后最矮的花的高度最高是多少。

直接对答案进行二分,对于高度X的判定,从左往右遍历花的高度,如果当前高度低于X,则用相应的天数浇水,如果天数不够就说明不可行。

至于处理方面,目测写个线段树、树状数组维护区间问题应该也可以,但也有比较简便的方法。

用一个数组b,初始化全部为0,再用一个变量C,初值也为0,如果当前需要浇水p天,则C+=p,表明后面的花也会浇到,在b[i+w]的位置减去p,表示当前的浇水的影响到这里结束,每访问到一个位置就先用C+b[i],然后再判断a[i]+C与x的大小关系。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n, m, w;
int a[100010], b[100010];
bool ok(int x){
    memset(b, 0, sizeof(b));
    int k = m;
    int c = 0;
    int p;
    for(int i=0; i<n; i++){
        c += b[i];
        if(a[i]+c<x){
            p = x-a[i]-c;
            if(p>k) return 0;//天数不足,不可行
            k-=p;
            c+=p;
            b[(i+w)>=n?n:(i+w)]-=p;
        }
    }
    return 1;
}
int main(){
    while(~scanf("%d %d %d", &n, &m, &w)){
        int low, top;
        for(int i=0; i<n; i++){
            scanf("%d", a+i);
            if(i){
                low = min(low, a[i]);
                top = max(top, a[i]);
            }
            else{
                low=top=a[i];
            }
        }
        top+=m;
        int ans = low;
        while(low<=top){
            int mid = (low+top)>>1;
            if(ok(mid)){
                ans = max(ans, mid);
                low = mid+1;
            }
            else{
                top = mid-1;
            }
        }
        printf("%d\n", ans);
    }
    return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值