【HDU3487】【splay分裂合并】Play with Chain
Problem Description
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?
Input
There will be multiple test cases in a test data.
For each test case, the first line contains two numbers: n and m (1≤n, m≤3*100000), indicating the total number of diamonds on the chain and the number of operations respectively.
Then m lines follow, each line contains one operation. The command is like this:
CUT a b c // Means a CUT operation, 1 ≤ a ≤ b ≤ n, 0≤ c ≤ n-(b-a+1).
FLIP a b // Means a FLIP operation, 1 ≤ a < b ≤ n.
The input ends up with two negative numbers, which should not be processed as a case.
For each test case, the first line contains two numbers: n and m (1≤n, m≤3*100000), indicating the total number of diamonds on the chain and the number of operations respectively.
Then m lines follow, each line contains one operation. The command is like this:
CUT a b c // Means a CUT operation, 1 ≤ a ≤ b ≤ n, 0≤ c ≤ n-(b-a+1).
FLIP a b // Means a FLIP operation, 1 ≤ a < b ≤ n.
The input ends up with two negative numbers, which should not be processed as a case.
Output
For each test case, you should print a line with n numbers. The ith number is the number of the ith diamond on the chain.
Sample Input
8 2
CUT 3 5 4
FLIP 2 6
-1 -1
Sample Output
1 4 3 7 6 2 5 8
Source
【分析】
果断被指针引用坑.......
调了一个半小时,本来想复习一下昨天的内容,结果被虐了。。
感觉pushdown和update出现的地方有些奇怪.
还有就是rotate里面的写法引用和不引用是不一样的。
昨天我两个都试了一下,今天就搞混了。。。。
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <cstring> 5 #include <vector> 6 #include <utility> 7 #include <iomanip> 8 #include <string> 9 #include <cmath> 10 #include <queue> 11 #include <assert.h> 12 #include <map> 13 #include <ctime> 14 #include <cstdlib> 15 #define LOCAL 16 const int MAXN = 500000 + 10; 17 const int INF = 100000000; 18 const int SIZE = 450; 19 const int maxnode = 0x7fffffff + 10; 20 using namespace std; 21 int M; 22 struct SPLAY{ 23 struct Node{ 24 int val, size; 25 bool turn; 26 Node *ch[2], *parent; 27 28 /*Node(){//暂时不要构造函数,节约时间 29 val = 0; 30 size = 0; 31 turn = 0; 32 parent = ch[0] = ch[1] = NULL; 33 }*/ 34 int cmp(){ 35 if (parent->ch[0] == this) return 0; 36 else return 1; 37 } 38 //更新 39 }*root, *nil, _nil, mem[MAXN]; 40 int tot; 41 42 void pushdown(Node *&t){ 43 if (t == nil) return; 44 if (t->turn){ 45 Node *p; 46 p = t->ch[0]; 47 t->ch[0] = t->ch[1]; 48 t->ch[1] = p; 49 50 if (t->ch[0] != nil) t->ch[0]->turn ^= 1; 51 if (t->ch[1] != nil) t->ch[1]->turn ^= 1; 52 t->turn = 0; 53 } 54 } 55 void update(Node *&t){ 56 t->size = 1; 57 t->size += t->ch[0]->size + t->ch[1]->size; 58 } 59 Node* NEW(int val){ 60 Node *p = &mem[tot++]; 61 p->val = val; 62 p->size = 1; 63 p->turn = 0; 64 p->parent = p->ch[0] = p->ch[1] = nil; 65 return p; 66 } 67 void init(){ 68 //哨兵初始化 69 nil = &_nil; 70 _nil.val = _nil.size = _nil.turn = 0; 71 _nil.parent = _nil.ch[0] = _nil.ch[1] = nil; 72 73 tot = 0; 74 root = NEW(INF); 75 root->ch[1] = NEW(INF); 76 root->ch[1]->parent = root; 77 } 78 //1为右旋 79 /*void Rotate(Node *&t, int d){ 80 Node *p = t->parent; 81 pushdown(p); 82 pushdown(t); 83 pushdown(t->ch[d]); 84 //t = p->ch[d ^ 1];这句话是废话,真正的一句一处 85 p->ch[d ^ 1] = t->ch[d]; 86 if (t->ch[d] != nil) t->ch[d]->parent = p; 87 t->parent = p->parent; 88 if (p->parent != nil) p->ch[p->cmp()] = t; 89 t->ch[d] = p; 90 p->parent = t; 91 update(p);//注意这里为什么只要updatep是因为旋转是在伸展中使用的,因此t的更新在splay中 92 if (root == p) root = t;//换根 93 }*/ 94 void Rotate(Node *t, int d){ 95 Node *p = t->parent;//t的右旋对于p来说也是右旋 96 t = p->ch[d ^ 1]; 97 p->ch[d ^ 1] = t->ch[d]; 98 t->ch[d]->parent = p; 99 t->ch[d] = p; 100 t->parent = p->parent; 101 //注意,这里要更新的原因在于t并不是引用 102 if (t->parent != nil){ 103 if (t->parent->ch[0] == p) t->parent->ch[0] = t; 104 else if (t->parent->ch[1] == p) t->parent->ch[1] = t; 105 } 106 p->parent = t; 107 if (t->parent == nil) root = t; 108 //不用换回去了... 109 update(p); 110 update(t); 111 //t->update(); 112 } 113 void splay(Node *x, Node *y){ 114 pushdown(x); 115 while (x->parent != y){ 116 if (x->parent->parent == y){ 117 Rotate(x, x->cmp() ^ 1); 118 break; 119 }else{ 120 Rotate(x->parent, x->parent->cmp() ^ 1); 121 Rotate(x, x->cmp() ^ 1); 122 } 123 update(x); 124 } 125 update(x);//最后退出的update不要忘了 126 if (nil == y) root = x; 127 } 128 //找到第k小的数并将其伸展到y 129 void find(Node *y, int k){ 130 Node *x = root; 131 while (1){ 132 //if (x == nil) break;//注意我已经在init中插入了两个数 133 pushdown(x); 134 int tmp = (x->ch[0]->size); 135 if ((tmp + 1) == k) break; 136 if (k <= tmp) x = x->ch[0]; 137 else k -= tmp + 1, x = x->ch[1]; 138 } 139 pushdown(x); 140 splay(x, y); 141 } 142 //在pos位置后面插入一个数val 143 void Insert(int pos, int val){ 144 find(nil, pos + 1); 145 find(root, pos + 2);//时刻注意已经插入了两个INF 146 pushdown(root); 147 pushdown(root->ch[1]); 148 Node *p = NEW(val), *t = root->ch[1]; 149 //一定要拆开!!不能放在ch[1]->[0] 150 p->ch[1] = t; 151 t->parent = p; 152 root->ch[1] = p; 153 p->parent = root; 154 splay(p, nil); 155 } 156 //剪掉a,b位置的数并接到c位置后面 157 void Cut(int a, int b, int c){ 158 find(nil, a); 159 find(root, b + 2); 160 pushdown(root); 161 pushdown(root->ch[1]); 162 163 Node *p = root->ch[1]->ch[0]; 164 root->ch[1]->ch[0] = nil;//剪掉 165 update(root->ch[1]);///不要忘了更新 166 update(root); 167 168 find(nil, c + 1); 169 find(root, c + 2); 170 pushdown(root); 171 pushdown(root->ch[1]); 172 173 root->ch[1]->ch[0] = p; 174 p->parent = root->ch[1]; 175 update(root->ch[1]); 176 update(root); 177 splay(p, nil); 178 } 179 void Reverse(int l, int r){ 180 find(nil, l); 181 find(root, r + 2); 182 //print(root); 183 root->ch[1]->ch[0]->turn ^= 1; 184 Node *p = root->ch[1]->ch[0]; 185 splay(p, nil); 186 } 187 void print(Node *t){ 188 if (t == nil) return; 189 pushdown(t); 190 print(t->ch[0]); 191 if (t->val != INF){ 192 if (M != 1) {printf("%d ", t->val);M--;} 193 else printf("%d", t->val); 194 } 195 print(t->ch[1]); 196 } 197 }A; 198 int n, m; 199 200 void init(){ 201 A.init(); 202 //scanf("%d%d", &n, &m); 203 for (int i = 0; i < n; i++){ 204 A.Insert(i, i + 1); 205 } 206 //A.print(A.root); 207 } 208 void work(){ 209 for (int i = 1; i <= m; i++){ 210 char str[10]; 211 scanf("%s", str); 212 if (str[0] == 'C'){ 213 int a, b, c; 214 scanf("%d%d%d", &a, &b, &c); 215 A.Cut(a, b, c); 216 }else{ 217 int l, r; 218 scanf("%d%d", &l, &r); 219 A.Reverse(l, r); 220 } 221 //A.print(A.root); 222 } 223 M = n; 224 A.print(A.root); 225 } 226 227 int main(){ 228 229 while (scanf("%d%d", &n, &m)){ 230 if (n == -1 && m == -1) break; 231 init(); 232 //A.find(A.nil, 3); 233 //printf("%d", A.root->size); 234 work(); 235 printf("\n"); 236 } 237 return 0; 238 }