题意
现在需要你维护一个长度为n的序列,需要支持三种操作:
1.区间加 2.区间翻转 3.区间求最大值
题解
很明显splay裸题,复习了一下splay,感觉忘得一干二净
按下标建splay树
对于区间加和区间翻转:把l-1 splay到根,把r+1 splay到根的右儿子,然后直接对根的右儿子的左儿子打标记
做起来习惯把 [0,n+1] 转到 [1,n+2] 上
找的时候下传一下就好了,标记操作具体见代码
#include<cstdio>
#include<algorithm>
#define N 50010
using namespace std;
int n,m,root,sz,size[N],fa[N],ch[N][2],tag[N],v[N],mx[N],ans[N];
bool rev[N];
inline void update(int x){
if(x){
mx[x]=max(max(mx[ch[x][0]],mx[ch[x][1]]),v[x]);
size[x]=1;
if(ch[x][0]) size[x]+=size[ch[x][0]];
if(ch[x][1]) size[x]+=size[ch[x][1]];
}
}
inline int get(int x){return x==ch[fa[x]][1];}
inline void rotate(int x){
int old=fa[x],oldf=fa[fa[x]],opt=get(x);
ch[old][opt]=ch[x][opt^1],fa[ch[old][opt]]=old;
ch[x][opt^1]=old,fa[old]=x;
fa[x]=oldf;
if(oldf) ch[oldf][ch[oldf][1]==old]=x;
update(old),update(x);
}
inline void splay(int x,int rt){
for(int fat=fa[x];fat!=rt;rotate(x),fat=fa[x])
if(fa[fat]!=rt) rotate((get(x)==get(fat))?fat:x);
if(!rt) root=x;
}
inline void pushdown(int x){
if(tag[x]){
if(ch[x][0]) v[ch[x][0]]+=tag[x],mx[ch[x][0]]+=tag[x],tag[ch[x][0]]+=tag[x];
if(ch[x][1]) v[ch[x][1]]+=tag[x],mx[ch[x][1]]+=tag[x],tag[ch[x][1]]+=tag[x];
tag[x]=0;
}
if(rev[x]) rev[ch[x][0]]^=1,rev[ch[x][1]]^=1,swap(ch[x][1],ch[x][0]),rev[x]=0;
}
void build(int l,int r,int fat){
if(l>r) return;
if(l==r){
fa[l]=fat,size[l]=1,ch[fat][l>fat]=l;
return;
}
int mid=l+r>>1;
build(l,mid-1,mid),build(mid+1,r,mid);
fa[mid]=fat,update(mid),ch[fat][mid>fat]=mid;
}
inline int find(int rt,int x){
if (tag[rt]||rev[rt]) pushdown(rt);
if (size[ch[rt][0]]>=x) return find(ch[rt][0],x);
if (size[ch[rt][0]]+1==x) return rt;
return find(ch[rt][1],x-size[ch[rt][0]]-1);
}
inline void change(int l,int r,int add){
int x=find(root,l),y=find(root,r+2);
splay(x,0),splay(y,x);
int tmp=ch[y][0];
tag[tmp]+=add,mx[tmp]+=add,v[tmp]+=add;
}
inline void change1(int l,int r){
int x=find(root,l),y=find(root,r+2);
splay(x,0),splay(y,x);
rev[ch[y][0]]^=1;
}
inline int query(int l,int r){
int x=find(root,l),y=find(root,r+2);
splay(x,0),splay(y,x);
return mx[ch[y][0]];
}
int main(){
scanf("%d%d",&n,&m);mx[0]=-2e9;
build(1,n+2,0),root=(n+3)>>1;
int opt,l,r,v;
while(m--){
scanf("%d%d%d",&opt,&l,&r);
switch(opt){
case 1:scanf("%d",&v),change(l,r,v);break;
case 2:change1(l,r);break;
case 3:printf("%d\n",query(l,r));break;
}
}
return 0;
}