标签:
题目大意:给出1到n的有序数列,现在有两个操作:
1.CUT a b c 把第a到第b个数剪切下来,放到剩下的第c个数的后边。
2.FLIP a b 把第a到第b个数反转。
经过总共m次操作后,求现在的数列。
n,m<300000
分析:典型的splay题。包含的操作即:查找第k大,剪切,插入,反转等操作。
维护size,rev(反转标记)即可。
通过size可以找到第k大,通过rev做懒标记,可以进行反转。
具体说就是,比如要剪切CUT a,b,c,以先把第a-1个节点splay到根的位置,然后把第b+1个节点spaly到根的右儿子的位置,则a到b这一段就刚好是根的右儿子的左子树了,然后把它剪切下来。再把第c节点splay到根的位置,把第c+1个节点splay到根的右儿子的位置,再把刚才剪切的那一段接在根的右儿子的左儿子位置即可。FLIP a b的话,先把第a-1个节点splay到根的位置,把第b+1个节点splay到根的右儿子的位置,然后对根的右儿子的左子树打上懒标记即可。注意:打蓝标记应该是tree[i].rev^=1,而不是tree[i].rev=1。我就是这样wa了一次。
因为splay树的伸展特性,splay树中要增加两个额外的虚拟节点,即头节点和尾节点。初始时把头结点作为根节点,把尾节点作为根的右儿子。有效节点作为根的左儿子的右子树。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 using namespace std; 5 #define MAXN 300505 6 int tot,root,n,m,a,b,c; 7 char str[10]; 8 struct node 9 { 10 int val,fa,sz; 11 bool rev; 12 int ch[2]; 13 }tree[MAXN]; 14 void newnode(int &r,int father,int val) 15 { 16 tot++; 17 r=tot; 18 tree[tot].fa=father; 19 tree[tot].val=val; 20 } 21 void build(int &root,int l,int r,int father) 22 { 23 if(l>r)return; 24 int mid=(l+r)/2; 25 newnode(root,father,mid); 26 build(tree[root].ch[0],l,mid-1,root); 27 build(tree[root].ch[1],mid+1,r,root); 28 tree[root].sz=tree[tree[root].ch[0]].sz+tree[tree[root].ch[1]].sz+1; 29 } 30 void init() 31 { 32 tot=root=0; 33 memset(tree,0,sizeof tree); 34 newnode(root,0,-1); 35 newnode(tree[root].ch[1],root,-1); 36 build(tree[tree[1].ch[1]].ch[0],1,n,tree[1].ch[1]); 37 tree[tree[1].ch[1]].sz=tree[tree[tree[1].ch[1]].ch[0]].sz+1; 38 tree[1].sz=tree[tree[1].ch[1]].sz+1; 39 } 40 void pd(int &r) 41 { 42 if(tree[r].rev==1) 43 {swap(tree[r].ch[0],tree[r].ch[1]); 44 tree[tree[r].ch[0]].rev^=1; 45 tree[tree[r].ch[1]].rev^=1; 46 tree[r].rev=0; 47 } 48 49 } 50 void pu(int &r) 51 { 52 tree[r].sz=tree[tree[r].ch[0]].sz+tree[tree[r].ch[1]].sz+1; 53 } 54 void rotato(int &r,bool kind) 55 { 56 int y=tree[r].fa; 57 int yy=tree[y].fa; 58 if(yy) 59 { 60 tree[yy].ch[tree[yy].ch[1]==y]=r; 61 } 62 tree[r].fa=yy; 63 tree[tree[r].ch[kind]].fa=y; 64 tree[y].ch[!kind]=tree[r].ch[kind]; 65 tree[y].fa=r; 66 tree[r].ch[kind]=y; 67 pu(y); 68 pu(r); 69 } 70 void splay(int &r,int goal) 71 { 72 while(tree[r].fa!=goal) 73 { 74 int y=tree[r].fa; 75 int yy=tree[y].fa; 76 if(yy==goal)rotato(r,tree[y].ch[0]==r); 77 else 78 { 79 int kind=(tree[y].ch[0]==r); 80 if(tree[yy].ch[kind]==y) 81 { 82 rotato(r,kind); 83 rotato(r,!kind); 84 } 85 else 86 { 87 rotato(y,kind); 88 rotato(r,kind); 89 } 90 } 91 } 92 if(goal==0) 93 root=r; 94 } 95 int find(int r,int k) 96 { 97 pd(r); 98 if(tree[tree[r].ch[0]].sz==k-1) 99 return r; 100 else if(tree[tree[r].ch[0]].sz>k-1) 101 return find(tree[r].ch[0],k); 102 else return find(tree[r].ch[1],k-tree[tree[r].ch[0]].sz-1); 103 } 104 void print(int &r) 105 { 106 pd(r); 107 if(tree[r].ch[0]) 108 print(tree[r].ch[0]); 109 if(tree[r].val!=-1){printf("%d",tree[r].val);if(tot>3)printf(" ");tot--;} 110 if(tree[r].ch[1]) 111 print(tree[r].ch[1]); 112 } 113 int main() 114 { 115 116 while(scanf("%d%d",&n,&m)&&(n>=0&&m>=0)) 117 { 118 init(); 119 for(int i=0;i<m;i++) 120 { 121 scanf("%s",str); 122 if(str[0]==‘C‘) 123 { 124 scanf("%d%d%d",&a,&b,&c); 125 int x1=find(root,a); 126 int y1=find(root,b+2); 127 splay(x1,0); 128 splay(y1,root); 129 int t=tree[tree[root].ch[1]].ch[0]; 130 tree[tree[root].ch[1]].ch[0]=0; 131 pu(tree[root].ch[1]); 132 pu(root); 133 x1=find(root,c+1); 134 y1=find(root,c+2); 135 splay(x1,0); 136 splay(y1,root); 137 tree[tree[root].ch[1]].ch[0]=t; 138 tree[t].fa=tree[root].ch[1]; 139 pu(tree[root].ch[1]); 140 pu(root); 141 } 142 else 143 { 144 scanf("%d%d",&a,&b); 145 int x=find(root,a); 146 int y=find(root,b+2); 147 splay(x,0); 148 splay(y,root); 149 tree[tree[tree[root].ch[1]].ch[0]].rev^=1; 150 } 151 } 152 print(root); 153 printf("\n"); 154 } 155 }
标签:
原文地址:http://www.cnblogs.com/hefenghhhh/p/4650519.html