题意:区间加,区间翻转,区间最大值(直接打tag就可以了)
第一次背着打模板...
注意几个点---- 提取L--R时,不能直接Splay(l-1) ...
我们要找到l-1对应的节点,也就是找第l-1大,然后再Splay
找第K大及其余操作时,每次都要Pushdown
发正Pushdown也没多慢,多push几次保险嘛
另外,前后多差一个,维护的序列是2--n+1 (因为提取区间要找L-1)
#include<bits/stdc++.h>
#define N 50005
#define lc t[x].ch[0]
#define rc t[x].ch[1]
using namespace std;
struct Splay{int ch[2],fa,tag,val,Max,lazy,siz;}t[N];
int n,m,rt,tot;
int read(){
int cnt=0,f=1;char ch=0;
while(!isdigit(ch)){ch=getchar();if(ch=='-')f=-1;}
while(isdigit(ch))cnt=cnt*10+(ch-'0'),ch=getchar();
return cnt*f;
}
void Pushup(int x){
t[x].Max=t[x].val;
t[x].siz = t[lc].siz + t[rc].siz + 1;
if(lc && t[lc].Max>t[x].Max) t[x].Max=t[lc].Max;
if(rc && t[rc].Max>t[x].Max) t[x].Max=t[rc].Max;
}
void Pushdown(int x){
if(t[x].tag){
swap(lc,rc);
t[lc].tag^=1,t[rc].tag^=1;
t[x].tag=0;
}
if(t[x].lazy){
t[lc].val+=t[x].lazy;
t[lc].lazy+=t[x].lazy;
t[lc].Max+=t[x].lazy;
t[rc].val+=t[x].lazy;
t[rc].lazy+=t[x].lazy;
t[rc].Max+=t[x].lazy;
t[x].lazy=0;
}
}
void build(int &x,int l,int r,int fa){
if(l>r) return;
int mid=(l+r)>>1; x=mid;
t[x].siz++; t[x].fa=fa;
build(lc,l,mid-1,x);
build(rc,mid+1,r,x);
Pushup(x);
}
void rotate(int x){
int y=t[x].fa,z=t[y].fa;
int k=t[y].ch[1]==x;
t[z].ch[t[z].ch[1]==y]=x;
t[x].fa=z;
t[y].ch[k]=t[x].ch[k^1];
t[t[x].ch[k^1]].fa=y;
t[x].ch[k^1]=y,t[y].fa=x;
Pushup(y),Pushup(x);
}
void Splay(int x,int goal){
while(t[x].fa!=goal){
int y=t[x].fa,z=t[y].fa;
if(z!=goal)
(t[y].ch[0]==x)^(t[z].ch[0]==y)?rotate(x):rotate(y);
rotate(x);
}if(goal==0) rt=x;
}
int Kth(int x,int k){
Pushdown(x);
if(t[lc].siz>=k) return Kth(lc,k);
if(t[lc].siz+1<k) return Kth(rc,k-t[lc].siz-1);
return x;
}
void Add(int l,int r,int val){
int pre=Kth(rt,l-1),suf=Kth(rt,r+1);
Splay(pre,0) , Splay(suf,pre);
t[t[suf].ch[0]].lazy += val;
t[t[suf].ch[0]].val += val;
t[t[suf].ch[0]].Max += val;
}
void Solve(int l,int r){
int pre=Kth(rt,l-1),suf=Kth(rt,r+1);
Splay(pre,0) , Splay(suf,pre);
t[t[suf].ch[0]].tag^=1;
}
int Quary(int l,int r){
int pre=Kth(rt,l-1),suf=Kth(rt,r+1);
Splay(pre,0) , Splay(suf,pre);
return t[t[suf].ch[0]].Max;
}
int main(){
int n=read(),m=read();
build(rt,1,n+2,0);
while(m--){
int op=read(),x=read()+1,y=read()+1;
if(op==1){int v=read();Add(x,y,v);}
if(op==2) Solve(x,y);
if(op==3) printf("%d\n",Quary(x,y));
}
return 0;
}