注意pushup的时候要先判断有没有左右儿子。因为有负数,所以这个可能会出bug。
很烦带标记的数据结构啊。。。秉承这样一个思路:只要局部的标记下方吗没有问题,整个程序应该都不会怎么出问题。
也就是思路要顺着程序而不是顺着标记。
#include<iostream> #include<cstdio> #include<cstring> #define maxn 100500 #define inf 1000000007 using namespace std; int n,m,root,value[maxn],size[maxn],tree[maxn][3],fath[maxn],add[maxn],rev[maxn],num[maxn]; int k,l,r,v; void pushup(int now) { int ls=tree[now][1],rs=tree[now][2]; num[now]=value[now]; if (ls) num[now]=max(num[now],num[ls]); if (rs) num[now]=max(num[now],num[rs]); size[now]=size[ls]+size[rs]+1; } void build(int left,int right,int father) { if (left>right) return; int now=left; if (left==right) { fath[now]=father;size[now]=1; if (now<father) tree[father][1]=now; else tree[father][2]=now; return; } int mid=(left+right)>>1; now=mid; fath[now]=father;size[now]=1; if (now<father) tree[father][1]=now; else tree[father][2]=now; build(left,mid-1,mid); build(mid+1,right,mid); pushup(mid); } void pushdown(int now) { int ls=tree[now][1],rs=tree[now][2]; if (rev[now]) { rev[now]=0;rev[ls]^=1;rev[rs]^=1; swap(tree[now][1],tree[now][2]); } if (add[now]) { if (ls) {num[ls]+=add[now];add[ls]+=add[now];value[ls]+=add[now];} if (rs) {num[rs]+=add[now];add[rs]+=add[now];value[rs]+=add[now];} add[now]=0; } } void rotate(int x,int &k) { int y=fath[x],z=fath[y],l,r; if (tree[y][1]==x) l=1;else l=2; r=3-l; if (y==k) k=x; else { if (tree[z][1]==y) tree[z][1]=x; else tree[z][2]=x; } fath[x]=z;fath[y]=x;fath[tree[x][r]]=y; tree[y][l]=tree[x][r];tree[x][r]=y; pushup(y);pushup(x); } void splay(int x,int &k) { while (x!=k) { int y=fath[x],z=fath[y]; if (y!=k) { if ((tree[y][1]==x)^(tree[z][1]==y)) rotate(x,k); else rotate(y,k); } rotate(x,k); } } int find(int rank,int now) { pushdown(now); int ls=tree[now][1],rs=tree[now][2]; if (rank<=size[ls]) return find(rank,ls); else if (rank>size[ls]+1) return find(rank-size[ls]-1,rs); else return now; } void work1() { scanf("%d%d%d",&l,&r,&v); int x=find(l,root),y=find(r+2,root); splay(x,root);splay(y,tree[x][2]); int r=tree[y][1]; add[r]+=v;value[r]+=v;num[r]+=v; } void work2() { scanf("%d%d",&l,&r); int x=find(l,root),y=find(r+2,root); splay(x,root);splay(y,tree[x][2]); int r=tree[y][1];rev[r]^=1; } void work3() { scanf("%d%d",&l,&r); int x=find(l,root),y=find(r+2,root); splay(x,root);splay(y,tree[x][2]); int r=tree[y][1];printf("%d\n",num[r]); } int main() { scanf("%d%d",&n,&m); root=(n+3)>>1; build(1,n+2,0); for (int i=1;i<=m;i++) { scanf("%d",&k); if (k==1) work1(); else if (k==2) work2(); else work3(); } return 0; }