Loj #6279. 数列分块入门 3
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\n",query()); else update(); } return 0; }
我爱学习,学习使我快乐