8 2 CUT 3 5 4 FLIP 2 6 -1 -1
1 4 3 7 6 2 5 8
CUT l r c:把第l-1节点splay到root节点,把第r+1节点splay到 ch[root][1] 节点,ch[ch[root][1]][0]为根的子树就是要剪切掉的部分
插入时:把第 c 节点splay到root节点,把第c的后继结点节点splay到 ch[root][1] 节点,此时ch[ch[root][1]][0]为根的子树就为空树,此时就可以把剪切掉的那部分插入到ch[ch[root][1]][0]为根的子树上;
FLIP l r:翻转操作要用到延迟标记rev(类似于线段树),push_up,push_down,把第l-1节点splay到root节点,把第r+1节点splay到 ch[root][1] 节点,ch[ch[root][1]][0]为根的子树就是要翻转的部分(同剪切);
输出是利用中根遍历;
我的代码:(留着以后当模版用,O(∩_∩)O哈哈~)
#include<iostream> #include<cstring> #include<queue> #include<cstdio> #include<algorithm> #define N 500001 #define Key_value ch[ch[root][1]][0] using namespace std; int n,q; int key[N]; int size[N],pre[N],rev[N]; int ch[N][2],tot,root,data[N]; void newnode(int &r,int k,int father){ r=++tot; ch[r][0]=ch[r][1]=0; pre[r]=father; rev[r]=0; key[r]=k; size[r]=1; } void push_up(int r){ size[r]=size[ch[r][0]]+size[ch[r][1]]+1; } void push_down(int r){ if(rev[r]){ swap(ch[r][0],ch[r][1]); rev[ch[r][0]]^=1; rev[ch[r][1]]^=1; rev[r]=0; } } int flag; void Inorder(int r) { if(r==0) return; push_down(r); Inorder(ch[r][0]); if(key[r]!=-1) { if(flag) { printf("%d",key[r]);flag=0; } else printf(" %d",key[r]); } Inorder(ch[r][1]); } void Rotate(int x,int kind){ int y=pre[x]; push_down(y); push_down(x); ch[y][!kind]=ch[x][kind]; pre[ch[x][kind]]=y; if(pre[y]) ch[pre[y]][ch[pre[y]][1]==y]=x; pre[x]=pre[y]; ch[x][kind]=y; pre[y]=x; push_up(y); } void Splay(int r,int goal){ push_down(r); while(pre[r]!=goal){ if(pre[pre[r]]==goal) Rotate(r,ch[pre[r]][0]==r); else{ int y=pre[r]; int kind=(ch[pre[y]][0]==y); if(ch[y][kind]==r){ Rotate(r,!kind); Rotate(r,kind); } else{ Rotate(y,kind); Rotate(r,kind); } } } push_up(r); if(goal==0) root=r; } void RotateTo(int k,int goal) { int r=root; push_down(r); while(size[ch[r][0]]!=k){ if(k<size[ch[r][0]]){ r=ch[r][0]; } else { k-=(size[ch[r][0]]+1); r=ch[r][1]; } push_down(r); } Splay(r,goal); } int Get_Kth(int r,int k){ push_down(r); int t=size[ch[r][0]]+1; if(t==k) return r; if(t>k) return Get_Kth(ch[r][0],k); else return Get_Kth(ch[r][1],k-t); } int Get_Min(int r){ push_down(r); while(ch[r][0]){ r=ch[r][0]; push_down(r); } return r; } int Get_Max(int r){ push_down(r); while(ch[r][1]){ r=ch[r][1]; push_down(r); } return r; } void Reversal(int l,int r){ RotateTo(l-1,0); RotateTo(r+1,root); rev[Key_value]^=1; } void build(int &r,int L,int R,int fa) { if(L>R) return; int mid=(L+R)/2; newnode(r,data[mid],fa); build(ch[r][0],L,mid-1,r); build(ch[r][1],mid+1,R,r); push_up(r); } void Init() { tot=root=0; ch[0][0]=ch[0][1]=pre[0]=size[0]=0; newnode(root,-1,0); newnode(ch[root][1],-1,root); //size[root]=2; for(int i=1;i<=n;i++) data[i]=i; build(Key_value,1,n,ch[root][1]); push_up(ch[root][1]); push_up(root); } void ins(int c,int r) { RotateTo(c,0); int x=Get_Min(ch[root][1]); Splay(x,root); Key_value=r; pre[Key_value]=ch[root][1]; } int Delete(int l,int r) { RotateTo(l-1,0); RotateTo(r+1,root); int kk; kk=Key_value; pre[Key_value]=0; Key_value=0; push_up(ch[root][1]); push_up(root); return kk; } char str[10]; int main(){ //freopen("editor1.in","r",stdin); while(scanf("%d%d",&n,&q)!=EOF){ if(n==-1&&q==-1) break; Init(); int k,l,r,c; while(q--){ scanf("%s",str); if(str[0]=='C'){ scanf("%d%d%d",&l,&r,&c); getchar(); k=Delete(l,r); ins(c,k); } else if(str[0]=='F'){ scanf("%d%d",&l,&r); getchar(); Reversal(l,r); } } flag=1; Inorder(root); printf("\n"); } return 0; }