一个长度为n的数列,初始状态为1,2...n。现有两种操作,CUT a,b,c 将从a开始到b结束这段数取出,并把这段插入到取出之后这个数列的第c个数后面;FLIP a,b 将从a开始到c结束的这段数颠倒顺序。 还是基本的splay操作,为了操作方便,先添加虚拟的头结点和尾节点,再把这串数插入到头尾之间。CUT操作就把a伸展到根,把b+2伸展到根的下面,这样b+2的左孩子就是目标段a+1,b+1了(因为有个虚拟节点所以a+1,b+1对应的就是原先的a,b),然后删掉b+2的左子树,再把c伸展到根,c+1伸展到根的下面,把刚刚删除的子树插入到根的右孩子的左孩子就ok了。FLIP还是把a伸展到根,b+2伸展到根的下面,给目标段上标记就可以了。最后中序遍历的时候不要忘了下传下标..
一个长度为n的数列,初始状态为1,2...n。现有两种操作,CUT a,b,c 将从a开始到b结束这段数取出,并把这段插入到取出之后这个数列的第c个数后面;FLIP a,b 将从a开始到c结束的这段数颠倒顺序。 还是基本的splay操作,为了操作方便,先添加虚拟的头结点和尾节点,再把这串数插入到头尾之间。CUT操作就把a伸展到根,把b+2伸展到根的下面,这样b+2的左孩子就是目标段a+1,b+1了(因为有个虚拟节点所以a+1,b+1对应的就是原先的a,b),然后删掉b+2的左子树,再把c伸展到根,c+1伸展到根的下面,把刚刚删除的子树插入到根的右孩子的左孩子就ok了。FLIP还是把a伸展到根,b+2伸展到根的下面,给目标段上标记就可以了。最后中序遍历的时候记得下传下标...
#include <iostream> #include <cstdio> #include <algorithm> #include <memory.h> #include <cmath> #include <string> #include <cstring> using namespace std; typedef long long ll; const int maxn=300000+300; int pre[maxn],ch[maxn][2]; int size[maxn],key[maxn]; int flip[maxn]; int root,n; int tot; int m,p,q,r,t,tt; int k1,k2; int a[maxn]; int b[maxn]; int num; struct splaytree { void pushup(int r) { size[r]=1+size[ch[r][0]]+size[ch[r][1]]; } void go_f(int r) { flip[r]^=1; swap(ch[r][0],ch[r][1]); } void pushdown(int r) { if (flip[r]) { go_f(ch[r][0]); go_f(ch[r][1]); flip[r]=0; } } void rotate(int x,int kind) { int y=pre[x]; pushdown(y); pushdown(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; pushup(y); pushup(x); } void splay(int x,int tgt) { pushdown(x); while(pre[x]!=tgt) { int y=pre[x]; pushdown(pre[y]); pushdown(y); pushdown(x); if (pre[pre[x]]==tgt) { rotate(x,ch[pre[x]][0]==x); } else { int kind=ch[pre[y]][0]==y; if (ch[y][kind]==x) { rotate(x,kind^1); rotate(x,kind); } else { rotate(y,kind); rotate(x,kind); } } } pushup(x); if (tgt==0) root=x; } void select(int k,int tgt) { int rt=root; pushdown(rt); while(true) { if (k<=size[ch[rt][0]]) rt=ch[rt][0]; else if (k==size[ch[rt][0]]+1) break; else k-=(size[ch[rt][0]]+1),rt=ch[rt][1]; pushdown(rt); } splay(rt,tgt); } void newnode(int &r,int father,int k) { r=++tot; pre[r]=father; size[r]=1; flip[r]=0; key[r]=k; ch[r][0]=ch[r][1]=0; } void build(int l,int r,int &x,int rt) { if (l>r) return; int m=(l+r)>>1; newnode(x,rt,m); build(l,m-1,ch[x][0],x); build(m+1,r,ch[x][1],x); pushup(x); } void init() { tot=root=0; newnode(root,0,0); newnode(ch[root][1],root,0); build(1,n,ch[ch[root][1]][0],ch[root][1]); pushup(ch[root][1]); pushup(root); } void Flip(int p1,int p2) { select(p1,0); select(p2+2,root); go_f(ch[ch[root][1]][0]); } void cut(int l1,int l2,int l3) { int t; select(l1,0); select(l2+2,root); t=ch[ch[root][1]][0]; pre[t]=0; ch[ch[root][1]][0]=0; pushup(ch[root][1]); select(l3+1,0); select(l3+2,root); ch[ch[root][1]][0]=t; pre[t]=ch[root][1]; } void print(int rt) { if (rt==0) return; pushdown(rt); print(ch[rt][0]); if (key[rt]) { num++; b[num]=key[rt]; } print(ch[rt][1]); } void out() { num=0; print(root); for (int i=1; i<num; i++) printf("%d ",b[i]); printf("%d\n",b[num]); } }spt; char cmd[20]; int x,y,z; int main() { // freopen("in.txt","r",stdin); while(~scanf("%d%d\n",&n,&m) && (n!=-1 || m!=-1)) { spt.init(); for (int i=1; i<=m; i++) { scanf("%s ",cmd); if (cmd[0]=='C') { scanf("%d%d%d",&x,&y,&z); spt.cut(x,y,z); } else { scanf("%d%d",&x,&y); spt.Flip(x,y); } } spt.out(); } return 0; }