题意:给出n和q,n代表1-n的序列,接下来q有两种操作,Cut a b c:表示把区间[a,b]截掉然后放在第c个数的后面,Flip a b 表示把区间[a,b]反转,经过一系列的q操作,最后输出操作后的序列:
分析:首先建立初始化的树结构之前,先给n设置个极限范围0和n+1,防止特殊情况下越界,如果反转[a,b],则先把第a-1个数放在根节点,把b+1结点的数放在根节点的右儿子下面,此时根节点的右儿子的左儿子为根的子树就是[a,b]区间,然后把反转标记传递给该子树的根节点,如果剪切区间[a,b]则把第c+1个数旋转到根节点处,然后把根节点的右儿子为子树的最左面的节点旋转到该子树的根,此时把剪掉的子树的根节点连到根节点的右儿子的左儿子上面即可,需要注意的是,push_down和push_up的操作
codes:指针
#include"stdio.h" #include"iostream" #include"queue" using namespace std; struct Link_cut { queue<int>q; struct node //节点结构体 { int key,val,son,flag; node *lson,*rson,*fa; //左儿子,右儿子,以及父节点 node() { key=val=flag=0; son=1; lson=rson=fa=NULL; } }; node *top,*root,*x,*y; void init() //建立根节点root的父节点top { top=new node(); } int getNum(node *x) //以x为根的子树一共有多少个节点 { if(x==NULL)return 0; return x->son; } void push_up(node *rt) { rt->son=getNum(rt->lson)+getNum(rt->rson)+1; } void push_down(node *rt) { if(rt==NULL)return; if(rt->flag) { rt->flag^=1; Reversal(rt); if(rt->lson!=NULL) rt->lson->flag^=1; if(rt->rson!=NULL) rt->rson->flag^=1; } } void Rotate(node *x,int k) //k=0左旋k=1右旋 { node *y=x->fa; if(k==0) { y->rson=x->lson; if(y->rson!=NULL) y->rson->fa=y; push_up(y); if(y->fa->rson==y) y->fa->rson=x; else y->fa->lson=x; x->fa=y->fa; x->lson=y; y->fa=x; } else { y->lson=x->rson; if(y->lson!=NULL) y->lson->fa=y; push_up(y); if(y->fa->lson==y) y->fa->lson=x; else y->fa->rson=x; x->fa=y->fa; x->rson=y; y->fa=x; } } void Splay(node *x,node *f)//把x旋转到f的下面 { while(x->fa!=f) { node *y=x->fa; node *z=y->fa; if(z==f) { if(y->rson==x) Rotate(x,0); else Rotate(x,1); } else { if(z->rson==y) { if(y->rson==x) { Rotate(y,0); Rotate(x,0); } else { Rotate(x,1); Rotate(x,0); } } else { if(y->lson==x) { Rotate(y,1); Rotate(x,1); } else { Rotate(x,0); Rotate(x,1); } } } } if(f==top) root=x; } void RotateTo(node *x,node *f) { Splay(x,f); push_up(x); } void RotateTo(int k,node *f) { node *x=root; k++; while(1) { push_down(x); int temp=getNum(x->lson)+1; if(k==temp)break; if(k<temp) x=x->lson; else { k-=temp; x=x->rson; } } Splay(x,f); push_up(x); } void creatTree(int l,int r,int k,node *f) //初始化一颗二叉树 { if(l>r)return; int mid=(l+r)/2; node *rt=new node(); if(f==top) root=rt; if(k==0) { f->lson=rt; rt->fa=f; rt->key=mid; } else { f->rson=rt; rt->fa=f; rt->key=mid; } creatTree(l,mid-1,0,rt); creatTree(mid+1,r,1,rt); push_up(rt); } void Reversal(node *x)//交换x左右儿子的结点 { if(x==NULL)return; node *y=x->lson; x->lson=x->rson; x->rson=y; } node *Find(int k) //找到第k的结点 { node *x=root; k++; while(1) { push_down(x); int temp=getNum(x->lson)+1; if(k==temp)break; else if(k<temp) x=x->lson; else { k-=temp; x=x->rson; } } return x; } node *FindRight(node *rt) //找到以rt为根节点的最右一个结点 { node *x=rt; while(1) { push_down(x); if(x->rson==NULL) break; x=x->rson; } return x; } node *FindLeft(node *rt) //找到以rt为根节点的最左一个结点 { node *x=rt; while(1) { push_down(x); if(x->lson==NULL)break; x=x->lson; } return x; } void Link(node *rt,int k) //把rt为根的子树连接到第k个结点的后面 { root->rson->lson=NULL; //把区间砍掉 node *x=Find(k); RotateTo(x,top); node *y=FindLeft(root->rson); RotateTo(y,root); root->rson->lson=rt; rt->fa=root->rson; } void Output(node *x,int n) { if(x==NULL)return; push_down(x); Output(x->lson,n); if(x->key>=1&&x->key<=n) q.push(x->key); Output(x->rson,n); } }h; int main() { int n,q; while(scanf("%d%d",&n,&q)!=-1) { if(n==-1&&q==-1)break; h.init(); h.creatTree(0,n+1,0,h.top); char op[11]; int a,b,c; while(q--) { scanf("%s%d%d",op,&a,&b); if(op[0]=='C') { scanf("%d",&c); h.RotateTo(a-1,h.top); h.RotateTo(b+1,h.root); h.Link(h.root->rson->lson,c); } else { h.RotateTo(a-1,h.top); h.RotateTo(b+1,h.root); h.root->rson->lson->flag^=1; } } while(!h.q.empty()) { h.q.pop(); } h.Output(h.root,n); printf("%d",h.q.front()); h.q.pop(); while(!h.q.empty()) { printf(" %d",h.q.front()); h.q.pop(); } puts(""); } } /* 8 1 CUT 3 5 4 5 1 CUT 2 3 1 8 3 Cut 3 6 3 Cut 2 6 2 Cut 3 6 4 8 1 Flip 2 6 10 5 Cut 2 6 3 Flip 4 9 Flip 5 8 Cut 6 7 3 Flip 4 5 */