1-n的序列,有两种操作:
1,将一段区间翻转
2,将一段区间切下来放到剩余序列的第C个数后
采用延迟更新的方法维护区间的翻转,并维护一个size域。
添加一个最大点和一个最小点,防止出界
翻转时,将第L-1个点伸展到跟,再将第R+1个点伸展到L-1的右子树,这时R+1的左子树就是要翻转的区间,加上一个标记。
切区间时,跟翻转操作差不多,只是不加标记。然后找到C+1和C,将C伸展到根,C+1伸展到C的右子树,此时C+1的左子树就是要插入的位置。
其实我说了这么多并没有什么卵用。。。。最后还是得自己画图看才能懂。
#include<stdio.h> #include<string.h> #include<iostream> using namespace std; const int N=3e5+111; int data[N],num[N],t[N][2],id,fa[N]; int flip[N],root,f; inline void pushup(int x){ num[x]=num[t[x][0]]+num[t[x][1]]+1; } inline void pushdown(int x){ if(flip[x]){ flip[x]=0; flip[t[x][0]]^=1; flip[t[x][1]]^=1; swap(t[x][0],t[x][1]); } } inline void Rotate(int x,int w){ int y=fa[x]; int z=fa[y]; pushdown(y); t[y][!w]=t[x][w]; fa[t[x][w]]=y; t[z][t[z][1]==y]=x; fa[x]=z; t[x][w]=y; fa[y]=x; pushup(y); } void newnode(int &x,int y,int v){ x=++id; t[x][0]=t[x][1]=0; fa[x]=y; data[x]=v,flip[x]=0; num[x]=1; } void build(int &x,int y,int l,int r){ if(l<=r){ int mid=(l+r)>>1; newnode(x,y,mid); build(t[x][0],x,l,mid-1); build(t[x][1],x,mid+1,r); pushup(x); } } void init(int n){ f=id=root=0; t[0][0]=t[0][1]=num[0]=data[0]=flip[0]=fa[0]=0; newnode(root,0,-1); newnode(t[1][1],root,-1); build(t[t[1][1]][0],t[1][1],1,n); pushup(t[1][1]); pushup(1); } void Splay(int x,int y){ if(x!=y){ pushdown(x); while(fa[x]!=y){ if(t[fa[x]][0]==x) Rotate(x,1); else Rotate(x,0); } pushup(x); if(!y)root=x; } } int Kth(int k){ int x=root; pushdown(root); for(;num[t[x][0]]+1!=k;){ if(num[t[x][0]]+1>k) x=t[x][0]; else k-=num[t[x][0]]+1,x=t[x][1]; pushdown(x); } return x; } void Flip(int a,int b){ a=Kth(a); b=Kth(b+2); Splay(a,0); Splay(b,a); flip[t[b][0]]^=1; } void Cut(int a,int b,int c){ int tmp,d; a=Kth(a);b=Kth(b+2); Splay(a,0);Splay(b,a); tmp=t[b][0];t[b][0]=0; pushup(b);pushup(a); d=Kth(c+2);c=Kth(c+1); Splay(c,0);Splay(d,c); t[d][0]=tmp;fa[tmp]=d; pushup(d);pushup(c); } void Inorder(int x){ if(x){ pushdown(x); Inorder(t[x][0]); if(data[x]>0){ if(f) putchar(' '); else f=1; printf("%d",data[x]); } Inorder(t[x][1]); } } int main(){ int n,m; char op[9]; while(scanf("%d%d",&n,&m)!=EOF){ if(n==-1)break; init(n); int a,b,c; while(m--){ scanf("%s",op); if(op[0]=='F'){ scanf("%d%d",&a,&b); Flip(a,b); }else{ scanf("%d%d%d",&a,&b,&c); Cut(a,b,c); } } Inorder(root); puts(""); } return 0; }