[BZOJ1251]序列终结者
[BZOJ1251]序列终结者
BZOJ
luogu
初学fhq_treap,调了真鸡儿久
感觉这东西比splay灵活,核心函数只有split和merge
其实码量倒是差不太多,splay也就一个rotate和一个splay
就把这题做入门题写了嗯嗯
#include<bits/stdc++.h>
using namespace std;
const int _=5e4+5;
int re(){
int x=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x*w;
}
int n,m,rt,tot;
int sz[_],ls[_],rs[_],mx[_],cov[_],rev[_],rd[_],val[_];
void rever(int x){rev[x]^=1;swap(ls[x],rs[x]);}
void cover(int x,int v){if(x)val[x]+=v,mx[x]+=v,cov[x]+=v;}
void pu(int x){
sz[x]=sz[ls[x]]+sz[rs[x]]+1;
mx[x]=max(val[x],max(mx[ls[x]],mx[rs[x]]));
}
void pd(int x){
if(rev[x])rever(ls[x]),rever(rs[x]),rev[x]=0;
if(cov[x])cover(ls[x],cov[x]),cover(rs[x],cov[x]),cov[x]=0;
}
void split(int x,int&l,int&r,int k){
if(!x){l=r=0;return;}pd(x);
if(k>=sz[ls[x]]+1)l=x,split(rs[x],rs[l],r,k-sz[ls[x]]-1),pu(l);
else r=x,split(ls[x],l,ls[r],k),pu(r);
}
void merge(int&x,int l,int r){
if(!l||!r){x=l|r;return;}pd(l);pd(r);
if(rd[l]>rd[r]){x=l;merge(rs[x],rs[l],r);}
else{x=r;merge(ls[x],l,ls[r]);}pu(x);
}
void add(int l,int r,int v){
int x,y,z;
split(rt,x,y,r);split(x,x,z,l-1);
cover(z,v);merge(x,x,z);merge(rt,x,y);
}
void reverse(int l,int r){
int x,y,z;
split(rt,x,y,r);split(x,x,z,l-1);
rever(z);merge(x,x,z);merge(rt,x,y);
}
int qmax(int l,int r){
int x,y,z,res;
split(rt,x,y,r);split(x,x,z,l-1);
res=mx[z];merge(x,x,z),merge(rt,x,y);
return res;
}
int main(){
srand(time(NULL));
n=re(),m=re();mx[0]=-1e9;
for(int i=1;i<=n;i++){
sz[i]=1;rd[i]=rand();merge(rt,rt,i);
}
int op,l,r,v;
while(m--){
op=re(),l=re(),r=re();
if(op==1)v=re(),add(l,r,v);
if(op==2)reverse(l,r);
if(op==3)printf("%d\n",qmax(l,r));
}
return 0;
}