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;
}