Present CodeForces - 460C (二分+线段树)

  二分最矮的花的高度即可。check函数就是判断一下花是否可以达到mid高度及以上,不能达到就给它浇水,这里还要判断浇水次数有没有超过m,超过了则mid不满足条件。然后因为每浇水一次区间值加+1,然后又需要单点查询,所以我这里用了线段树维护区间。

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
#define ll long long
struct node
{
    int l,r,tag,lazy,sum;
}tree[4*maxn];
vector<int>v;
int n,m,w;
void pushup(int rt)
{
    tree[rt].sum=tree[2*rt].sum+tree[2*rt+1].sum;
}
void pushdown(int rt)
{
    tree[2*rt].tag=1;
    tree[2*rt].lazy+=tree[rt].lazy;
    tree[2*rt].sum+=(tree[2*rt].r-tree[2*rt].l+1)*tree[rt].lazy;
    tree[2*rt+1].tag=1;
    tree[2*rt+1].lazy+=tree[rt].lazy;
    tree[2*rt+1].sum+=(tree[2*rt+1].r-tree[2*rt+1].l+1)*tree[rt].lazy;
    tree[rt].tag=tree[rt].lazy=0;
}
void build(int l,int r,int rt)
{
    tree[rt].l=l;
    tree[rt].r=r;
    tree[rt].lazy=tree[rt].tag=0;
    if(l==r)
        tree[rt].sum=v[l];
    else
    {
        int mid=(l+r)>>1;
        build(l,mid,2*rt);
        build(mid+1,r,2*rt+1);
        pushup(rt);
    }
}

void update(int l,int r,int rt,int v)
{
    if(tree[rt].l>=l&&tree[rt].r<=r)
    {
        tree[rt].tag=1;
        tree[rt].lazy+=v;
        tree[rt].sum+=(tree[rt].r-tree[rt].l+1)*v;
        return ;
    }
    int mid=(tree[rt].l+tree[rt].r)>>1;
    if(mid>=r)
        update(l,r,2*rt,v);
    else
        if(mid+1<=l)
            update(l,r,2*rt+1,v);
        else
        {
            update(l,r,2*rt,v);
            update(l,r,2*rt+1,v);
        }
    pushup(rt);
}
int query(int l,int r,int rt)
{
    if(tree[rt].l>=l&&tree[rt].r<=r)
        return tree[rt].sum;
    if(tree[rt].tag) pushdown(rt);
    int ans=0,mid=(tree[rt].l+tree[rt].r)>>1;
    if(mid>=r)
    {
        ans=query(l,r,2*rt);
    }
    else
        if(mid+1<=l)
            ans=query(l,r,2*rt+1);
        else
        {
            ans=query(l,r,2*rt);
            ans+=query(l,r,2*rt+1);
        }

    return ans;
}
bool check(int mid)
{
    int op=0,tmp;
    build(1,n,1);
    for(int i=1;i<=n;i++)
    {
        if(v[i]<mid)
        {
            if((tmp=query(i,i,1))<mid)
            {
                int up,v;
                if(i+w-1>n)
                {
                    up=n;
                }
                else
                    up=i+w-1;
                v=mid-tmp;
                if(v+op>m)
                     return false;
                op+=v;
                update(i,up,1,v);
            }

        }
    }
    return true;
}
int main()
{
    int low=0,up=1e9+1e5+10,mid;
    int ans=-1;
    v.push_back(0);
    scanf("%d %d %d",&n,&m,&w);
    for(int i=1;i<=n;i++)
    {
        int tmp;
        cin>>tmp;
        v.push_back(tmp);
    }
    while(low<=up)
    {
        mid=(low+up)>>1;

        if(check(mid))
        {
            ans=mid;
            low=mid+1;
        }
        else
            up=mid-1;
    }
    cout<<ans<<endl;
    return 0;


}

 

posted @ 2018-08-23 20:41  eason99  阅读(92)  评论(0编辑  收藏  举报