思路
二分
一看最小的最大就是二分了
线段树
二分时判断是否成立时用到
每次扫一遍,当有树高度小于mid时,增加这w个树的高度
区间修改单点查询
树状数组
区间修改单点查询可以用树状数组差分实现
于是我偷懒用了树状数组
可以封装使代码更简洁
代码
#include<bits/stdc++.h>
#define ll long long
#define N 100010
#define lowbit(x) x&-x
using namespace std;
int n,m,w;
ll a[N];
struct BIT{
ll c[N];
void _add(int x,ll v){
while(x<=n){
c[x]+=v;
x+=lowbit(x);
}
}
void add(int l,int r,ll v){
_add(l,v);
_add(r+1,-v);
}
ll operator[](int x){
ll ans=0;
while(x>0){
ans+=c[x];
x-=lowbit(x);
}
return ans;
}
BIT(){memset(c,0,sizeof(c));for(int i=1;i<=n;i++)_add(i,a[i]-a[i-1]);}
};//封装
bool check(ll ht){//1::not enough 2::too large
BIT b;
ll cm=m;
for(int i=1;i<=n;i++){
ll x=b[i];
if(x<ht){
if(i>=n-w+2){
b.add(n-w+1,n,ht-x);
}
else{
b.add(i,i+w-1,ht-x);
}
cm-=ht-x;
}
}
if(cm>=0)return 1;
else return 0;
}//判断是否合法
int main(){
cin>>n>>m>>w;
ll l=1,r=0,mid;
for(int i=1;i<=n;i++)cin>>a[i],r=max(a[i],r),l=min(a[i],l);
r+=m+1;
while(l<r-1){
mid=(l+r)>>1;
if(check(mid))l=mid;
else r=mid;
}//二分
cout<<l;
return 0;
}