我们只需存有序完整块,在查询 的前驱时,散块暴力遍历查找 的前驱,整块 lower_bound,最后将所有候选值取 即可。
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e5+7;
int a[N],b[N],s[N],id[N],n,len;
int blk[507][507],siz[507];
void sorted(int bid){
int l=(bid-1)*len+1;
int r=min(bid*len,n);
int j=0;
for(int i=l;i<=r;i++)blk[bid][++j]=a[i];
siz[bid]=j;
sort(blk[bid]+1,blk[bid]+siz[bid]+1);
}
void add(int l,int r,int x){
if(id[l]==id[r]){
for(int i=l;i<=r;i++)a[i]+=x,s[id[l]]+=x;
sorted(id[l]);
return;
}
for(int i=l;id[i]==id[l];i++)a[i]+=x,s[id[l]]+=x;
sorted(id[l]);
for(int i=id[l]+1;i<id[r];i++)b[i]+=x,s[i]+=len*x;
for(int i=r;id[r]==id[i];i--)a[i]+=x,s[id[r]]+=x;
sorted(id[r]);
}
int query(int l,int r,int c){
int ans=LLONG_MIN;
if(id[l]==id[r]){
for(int i=l;i<=r;i++){
if(a[i]+b[id[l]]<c)ans=max(ans,a[i]+b[id[l]]);
}
return ans;
}
for(int i=l;id[i]==id[l];i++)if(a[i]+b[id[i]]<c)ans=max(ans,a[i]+b[id[l]]);
for(int i=id[l]+1;i<id[r];i++){
int lp=c-b[i];
int *x=lower_bound(blk[i]+1,blk[i]+1+siz[i],lp);
if(x!=blk[i]+1){
int p=*(x-1);
ans=max(ans,p+b[i]);
}
}
for(int i=r;id[i]==id[r];i--)if(a[i]+b[id[i]]<c)ans=max(ans,a[i]+b[id[r]]);
return ans;
}
signed main(){
cin>>n;
len=sqrt(n);
int cnt=(n+len-1)/len;
for(int i=1;i<=n;i++){
cin>>a[i];
id[i]=(i-1)/len+1;
s[id[i]]+=a[i];
}
for(int i=1;i<=cnt;i++)sorted(i);
for(int i=1;i<=n;i++){
int opt,l,r,c;
cin>>opt>>l>>r>>c;
if(opt==0)add(l,r,c);
else{
int ans=query(l,r,c);
if(ans==LLONG_MIN)ans=-1;
cout<<ans<<endl;
}
}
}
暂无评论