hdu 3487 Play with Chain
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3487
YaoYao is fond of playing his chains. He has a chain containing n diamonds on it. Diamonds are numbered from 1 to n.
At first, the diamonds on the chain is a sequence: 1, 2, 3, …, n.
He will perform two types of operations:
CUT a b c: He will first cut down the chain from the ath diamond to the bth diamond. And then insert it after the cth diamond on the remaining chain.
For example, if n=8, the chain is: 1 2 3 4 5 6 7 8; We perform “CUT 3 5 4”, Then we first cut down 3 4 5, and the remaining chain would be: 1 2 6 7 8. Then we insert “3 4 5” into the chain before 5th diamond, the chain turns out to be: 1 2 6 7 3 4 5 8.
FLIP a b: We first cut down the chain from the ath diamond to the bth diamond. Then reverse the chain and put them back to the original position.
For example, if we perform “FLIP 2 6” on the chain: 1 2 6 7 3 4 5 8. The chain will turn out to be: 1 4 3 7 6 2 5 8
He wants to know what the chain looks like after perform m operations. Could you help him?
At first, the diamonds on the chain is a sequence: 1, 2, 3, …, n.
He will perform two types of operations:
CUT a b c: He will first cut down the chain from the ath diamond to the bth diamond. And then insert it after the cth diamond on the remaining chain.
For example, if n=8, the chain is: 1 2 3 4 5 6 7 8; We perform “CUT 3 5 4”, Then we first cut down 3 4 5, and the remaining chain would be: 1 2 6 7 8. Then we insert “3 4 5” into the chain before 5th diamond, the chain turns out to be: 1 2 6 7 3 4 5 8.
FLIP a b: We first cut down the chain from the ath diamond to the bth diamond. Then reverse the chain and put them back to the original position.
For example, if we perform “FLIP 2 6” on the chain: 1 2 6 7 3 4 5 8. The chain will turn out to be: 1 4 3 7 6 2 5 8
He wants to know what the chain looks like after perform m operations. Could you help him?
题意:题意比较简单,就给一个数列两种操作:1,CUT a,b,c,在原数列截取区间[a,b](a和b指数列a位置和b位置),然后剩下的数列合并在一起,把截取的区间放在那个数列的c 位置;2,FLIP a b 翻转区间[a,b]。
解法:伸展树+延迟标记。
1 ///*hdu 3487*/ 2 ///G++ 687ms C++ 609ms 3 #include<iostream> 4 #include<cstdio> 5 #include<cstring> 6 #include<cstdlib> 7 #include<cmath> 8 #include<algorithm> 9 #define inf 0x7fffffff 10 using namespace std; 11 const int maxn=3*1e6+10; 12 struct Splay_Tree 13 { 14 struct Node 15 { 16 Node *ch[2],*pre; ///节点的左儿子和右儿子,父亲节点 17 int value,size; ///节点的值和以此节点为根的子树的节点个数 18 bool rev; ///判断是否需要翻转 19 }*root,*null,*lb,*rb,node[maxn]; 20 int count; 21 bool flag; 22 Node *NewNode(int value,Node *father)///插入新节点 23 { 24 ///Node *e=node[++count];这样写不行 25 Node *e=node+(++count); 26 e->value=value; 27 e->size=1; 28 e->pre=father; 29 e->rev=false; 30 e->ch[0]=e->ch[1]=null; 31 return e; 32 } 33 void Update(Node *p)///更新节点p的信息 34 { 35 if (p==null) return; 36 p->size=p->ch[0]->size + p->ch[1]->size + 1; 37 } 38 void PushDown(Node *x)///向下更新标记 39 { 40 if (x==null) return; 41 if (x->rev) 42 { 43 x->rev=false; 44 Node *t=x->ch[0] ;x->ch[0]=x->ch[1] ;x->ch[1]=t; 45 x->ch[0]->rev= !x->ch[0]->rev; 46 x->ch[1]->rev= !x->ch[1]->rev; 47 } 48 } 49 void Rotate(Node *x,bool d)///右旋转:true;左旋转:false 50 { 51 Node *y=x->pre; 52 y->ch[!d]=x->ch[d]; 53 if (x->ch[d]!=null) x->ch[d]->pre=y; 54 x->pre=y->pre; 55 if (y->pre!=null) 56 { 57 if (y==y->pre->ch[d]) 58 y->pre->ch[d]=x; 59 else y->pre->ch[!d]=x; 60 } 61 x->ch[d]=y; 62 y->pre=x; 63 Update(y); 64 Update(x); 65 if (root==y) root=x; 66 } 67 void Splay(Node *x,Node *target)///伸展操作 68 { 69 PushDown(x); 70 Node *y; 71 while (x->pre!=target) 72 { 73 y=x->pre; 74 if (x==y->ch[0]) 75 { 76 if (y->pre!=target && y->pre->ch[0]==y) 77 Rotate(y,true); 78 Rotate(x,true); 79 } 80 else 81 { 82 if (y->pre!=target && y->pre->ch[1]==y) 83 Rotate(y,false); 84 Rotate(x,false); 85 } 86 } 87 Update(x); 88 } 89 void Select(int k,Node *y)///选择第k个位置的节点 90 { 91 Node *x=root; 92 PushDown(x); 93 while (k!=x->ch[0]->size+1) 94 { 95 if (k<=x->ch[0]->size) 96 x=x->ch[0]; 97 else 98 { 99 k -= x->ch[0]->size+1; 100 x=x->ch[1]; 101 } 102 PushDown(x); 103 } 104 Splay(x,y); 105 } 106 void MakeTree(int l,int r,int *an,Node *p,int side) 107 { 108 if (l>r) return; 109 int mid=(l+r)>>1; 110 Node *x; 111 x=NewNode(an[mid],p); 112 p->ch[side]=x; 113 MakeTree(l,mid-1,an,x,0); 114 MakeTree(mid+1,r,an,x,1); 115 Update(x); 116 } 117 ///****/// 118 ///在pos后面插入长度为cnt的区间 119 void Insert(int pos,int cnt,int *an) 120 { 121 Select(pos+1,null); 122 Select(pos+2,root); 123 MakeTree(1,cnt,an,root->ch[1],0); 124 Splay(root->ch[1]->ch[0],null); 125 } 126 ///删除pos后长度为cnt的区间 127 void Delete(int pos,int cnt,int ind) 128 { 129 Node *p1; 130 Select(pos,null); 131 Select(pos+cnt+1,root); 132 p1=root->ch[1]->ch[0]; 133 root->ch[1]->ch[0]=null; 134 135 Splay(root->ch[1],null); 136 Select(ind+1,null); 137 Select(ind+2,root); 138 root->ch[1]->ch[0]=p1; 139 Splay(root->ch[1],null);///注意不是Splay(root->ch[1]->ch[0],null) 140 } 141 ///旋转pos后长度为cnt的区间 142 void Reverse(int pos,int cnt) 143 { 144 Select(pos,null); 145 Select(pos+cnt+1,root); 146 root->ch[1]->ch[0]->rev= !root->ch[1]->ch[0]->rev; 147 Splay(root->ch[1]->ch[0],null); 148 } 149 void Index(int pos) 150 { 151 Select(pos+1,null); 152 printf("%d",root->value); 153 } 154 void Out()///调试程序 155 { 156 flag=false; 157 Print(root);///打印整个区间 158 printf("\n"); 159 } 160 void Print(Node *now)///打印区间 161 { 162 if (now==null) return; 163 if (now->ch[0]==null&&now->ch[1]==null) 164 { 165 if (now->value!=inf) 166 { 167 if (flag) printf(" "); 168 flag=true; 169 printf("%d",now->value); 170 } 171 return; 172 } 173 PushDown(now); 174 Print(now->ch[0]); 175 if (now->value!=inf) 176 { 177 if (flag) printf(" "); 178 flag=true; 179 printf("%d",now->value); 180 } 181 Print(now->ch[1]); 182 } 183 void init() 184 { 185 count=-1; 186 null=0; 187 null=NewNode(inf,0); 188 null->size=0; 189 lb=root=NewNode(inf,null); 190 rb=root->ch[1]=NewNode(inf,root); 191 Update(root); 192 } 193 }splay; 194 int an[maxn]; 195 int main() 196 { 197 int n,m; 198 199 char str[5]; 200 int a,b,c; 201 while (scanf("%d%d",&n,&m)!=EOF) 202 { 203 if (n<0 && m<0) break; 204 splay.init(); 205 for (int i=1 ;i<=n ;i++) an[i]=i; 206 splay.Insert(0,n,an); 207 while (m--) 208 { 209 scanf("%s",str); 210 if (str[0]=='C') 211 { 212 scanf("%d%d%d",&a,&b,&c); 213 splay.Delete(a,b-a+1,c); 214 } 215 else 216 { 217 scanf("%d%d",&a,&b); 218 splay.Reverse(a,b-a+1); 219 } 220 } 221 splay.Out(); 222 } 223 return 0; 224 }