link: https://loj.ac/problem/6279
分块基本操作之一。
分块套平衡树。
#include<bits/stdc++.h>
#define ll long long
#define maxn 100005
using namespace std;
const ll inf=1ll<<61ll;
ll a[maxn],tag[405];
multiset<ll> s[405];
multiset<ll> ::iterator it;
int n,opt,m,le,sz,w;
int ri,add,bl[maxn];
inline void update(){
if(bl[le]==bl[ri]){
for(;le<=ri;le++){
s[bl[le]].erase(a[le]);
a[le]+=(ll)w;
s[bl[le]].insert(a[le]);
}
}
else{
for(;bl[le]==bl[le-1];le++){
s[bl[le]].erase(a[le]);
a[le]+=(ll)w;
s[bl[le]].insert(a[le]);
}
for(;bl[ri]==bl[ri+1];ri--){
s[bl[ri]].erase(a[ri]);
a[ri]+=(ll)w;
s[bl[ri]].insert(a[ri]);
}
for(int j=bl[le];j<=bl[ri];j++){
tag[j]+=(ll)w;
}
}
}
inline ll query(){
ll an=-inf;
if(bl[le]==bl[ri]){
for(;le<=ri;le++){
if(a[le]+tag[bl[le]]<w) an=max(an,a[le]+tag[bl[le]]);
}
}
else{
for(;bl[le]==bl[le-1];le++){
if(a[le]+tag[bl[le]]<w) an=max(an,a[le]+tag[bl[le]]);
}
for(;bl[ri]==bl[ri+1];ri--){
if(a[ri]+tag[bl[ri]]<w) an=max(an,a[ri]+tag[bl[ri]]);
}
for(int j=bl[le];j<=bl[ri];j++){
it=s[j].lower_bound(w-tag[j]);
an=max(an,(*(--it))+tag[j]);
}
}
if(an==-inf) return -1;
else return an;
}
int main(){
scanf("%d",&n),sz=sqrt(n);
for(int i=1;i<=n;i++){
scanf("%lld",a+i);
bl[i]=(i-1)/sz+1;
s[bl[i]].insert(a[i]);
if(bl[i]!=bl[i-1]) s[bl[i]].insert(-inf*2ll);
}
for(int i=1;i<=n;i++){
scanf("%d%d%d%d",&opt,&le,&ri,&w);
if(opt) printf("%lld
",query());
else update();
}
return 0;
}