8 2 CUT 3 5 4 FLIP 2 6 -1 -1
1 4 3 7 6 2 5 8
题意:给一个从1到n的连续区间,做两个操作
1.把区间l---r的数字切割下来,接在剩下的序列的第n个数字后面
2把一个区间的序列反转
解题:splay 写好旋转,伸展操作,写个find函数查找区间第i个数字的位置即可,
然后用size记录节点个数,lz标记下这段区间是否需要反转,val记录节点的值
添加两个新节点在1的左边和n的右边,可以避免特殊判断
操作1:对于l,r,n , 查找l-1的位置提到根,查找r+1的位置提到根的右节点,然后 l---r区间的数都是r+1的左孩子了
把r+1的做孩子切割下来,然后把n提到根,n+1提到根的右节点,然后把l-r作为n+1的做孩子拼接上去即可
操作2:对于区间l,r 把l-1提到根,r+1提到根的右孩子,对于r+1的左孩子记录一个懒操作,表示要反转即可
只要在查找节点的时候记得push更新懒操作,在每次改变树的结构的时候,update一下就好了
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define maxn 5000001 int ch[maxn][2],fa[maxn],val[maxn],lz[maxn],root,cnt,size[maxn]; void init(){ cnt=1; root=ch[0][0]=ch[0][1]=0; val[0]=lz[0]=fa[0]=0; size[0]=0; } void update(int n){ size[n] = 1+size[ch[n][0]]+size[ch[n][1]]; } int build(int l,int r,int f){ if(r<l)return 0; fa[cnt]=f; int mid=(l+r)/2; val[cnt]=mid; int id=cnt++; size[id]=1; lz[id]=0; ch[id][0]=build(l,mid-1,id); ch[id][1]=build(mid+1,r,id); update(id); return id; } void push(int n){ if(lz[n]){ lz[n] = 0; swap(ch[n][0],ch[n][1]); lz[ch[n][0]]^=1; lz[ch[n][1]]^=1; } } void rotate(int n){ int f=fa[n],ff=fa[f]; int x=(ch[f][1]==n),x1=(ch[ff][1]==f); ch[ff][x1]=n; ch[f][x]=ch[n][!x]; ch[n][!x]=f; fa[ch[f][x]]=f; fa[f]=n; fa[n]=ff; update(f),update(n); } int find(int n){ int p = ch[root][1]; push(p); int l = size[p]-size[ch[p][1]]; while(l!=n){ if(l<n){ p=ch[p][1]; push(p); l=l+size[p]-size[ch[p][1]]; } else { p=ch[p][0]; push(p); l=l-1-size[ch[p][1]]; } } return p; } void splay(int n,int p){ while(fa[n]!=p){ int f=fa[n],ff=fa[f]; if(ff==p)rotate(n); else if((ch[f][1]==n)==(ch[ff][1]==f)) rotate(n),rotate(n); else rotate(f),rotate(n); } } int flag; void output(int n,int x){ if(n == 0) return ; push(n); output(ch[n][0],x); if(val[n] != 1 && val[n]!=x) { if(flag) printf(" "); printf("%d",val[n]-1);flag=1; } output(ch[n][1],x); } int main(){ int n,ope,l,r,u,v,p1,p2,q1,q2,q3; char word[5]; while(scanf("%d%d",&n,&ope),n>0&&ope>0){ init(); ch[root][1] = build(1,n+2,root); for(int i = 0;i < ope;i++){ scanf("%s",word); if(word[0] == 'C'){ scanf("%d%d%d",&l,&r,&u); l++,r++,u++; p1=find(l-1); splay(p1,root); p2=find(r+1); splay(p2,p1); q1=ch[p2][0]; ch[p2][0]=0; update(p2),update(p1); q2=find(u); splay(q2,root); q3=find(u+1); splay(q3,q2); ch[q3][0]=q1,fa[q1]=q3; update(q3),update(q2); } else { scanf("%d%d",&l,&r); l++,r++; p1=find(l-1); splay(p1,root); p2=find(r+1); splay(p2,p1); lz[ch[p2][0]]^=1; } } flag = 0; output(ch[root][1],n+2); cout<<endl; } return 0; }