有三种操作,区间加,于是我们给每个点加一个"lazy-lable",tag[i]表示以i为根的子树中每个点+tag[i](注意val[i]即i的权值已经加了tag[i]);区间反转,实质上就是将区间的左右子树反转,然而对于每次询问或修改,若不涉及到未翻转的子树,那么操作并没有什么影响,所以给每个点再加一个rev[i],rev[i]=1表示以i为根的左右子树需反转,每次操作将rev[i]^=1。对于
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#define inf 1000000000
using namespace std;
int n,m,cnt,root;
int fa[50005],tree[50005][2],id[50005];
int tag[50005],val[50005],mx[50005],size[50005];
bool rev[50005];
inline int read()
{
int a=0,f=1; char c=getchar();
while (c<‘0‘||c>‘9‘) {if (c==‘-‘) f=-1; c=getchar();}
while (c>=‘0‘&&c<=‘9‘) {a=a*10+c-‘0‘; c=getchar();}
return a*f;
}
inline void pushup(int k)
{
mx[k]=max(mx[tree[k][0]],mx[tree[k][1]]);
mx[k]=max(mx[k],val[k]);
size[k]=size[tree[k][0]]+size[tree[k][1]]+1;
}
inline void pushdown(int k)
{
int t=tag[k];
if (tag[k])
{
tag[k]=0;
if (tree[k][0]) {tag[tree[k][0]]+=t; val[tree[k][0]]+=t; mx[tree[k][0]]+=t;}
if (tree[k][1]) {tag[tree[k][1]]+=t; val[tree[k][1]]+=t; mx[tree[k][1]]+=t;}
}
if (rev[k])
{
rev[k]=0;
rev[tree[k][0]]^=1;rev[tree[k][1]]^=1;
swap(tree[k][0],tree[k][1]);
}
}
inline void rotate(int x,int &k)
{
int y=fa[x],z=fa[y],l=(tree[y][1]==x),r=l^1;
if (y==k) k=x;
else tree[z][tree[z][1]==y]=x;
fa[x]=z; fa[y]=x; fa[tree[x][r]]=y;
tree[y][l]=tree[x][r]; tree[x][r]=y;
pushup(y); pushup(x);
}
inline void splay(int x,int &k)
{
while (x!=k)
{
int y=fa[x],z=fa[y];
if (y!=k)
{
if ((tree[z][0]==y)^(tree[y][0]==x)) rotate(x,k); else rotate(y,k);
}
rotate(x,k);
}
}
int find(int k,int x)
{
if (tag[k]||rev[k]) pushdown(k);
if (size[tree[k][0]]+1==x) return k;
else if (size[tree[k][0]]>=x) return find(tree[k][0],x);
else return find(tree[k][1],x-size[tree[k][0]]-1);
}
inline void update(int l,int r,int v)
{
int x=find(root,l),y=find(root,r+2);
splay(x,root); splay(y,tree[root][1]);
tag[tree[y][0]]+=v;
val[tree[y][0]]+=v;
mx[tree[y][0]]+=v;
}
inline void build(int l,int r,int f)
{
if (l>r) return;
int now=id[l],last=id[f],mid=(l+r)>>1;
if (l==r)
{
fa[now]=last; size[now]=1;
if (l<f) tree[last][0]=now; else tree[last][1]=now;
return;
}
now=id[mid];
build(l,mid-1,mid); build(mid+1,r,mid);
fa[now]=last; pushup(now);
if (mid<f) tree[last][0]=now; else tree[last][1]=now;
}
inline void query(int l,int r)
{
int x=find(root,l),y=find(root,r+2);
splay(x,root); splay(y,tree[root][1]);
printf("%d\n",mx[tree[y][0]]);
}
inline void rever(int l,int r)
{
int x=find(root,l),y=find(root,r+2);
splay(x,root); splay(y,tree[root][1]);
rev[tree[y][0]]^=1;
}
int main()
{
mx[0]=-inf;
n=read(); m=read();
for (int i=1;i<=n+2;i++) id[i]=++cnt;
build(1,n+2,0); root=(n+3)>>1;
for (int i=1;i<=m;i++)
{
int f=read(),l=read(),r=read(),v;
if (f==1) {v=read(); update(l,r,v);}
if (f==2) rever(l,r);
if (f==3) query(l,r);
}
return 0;
}