Description
Your friend, Jackson is invited to a TV show called SuperMemo in which the participant is told to play a memorizing game. At first, the host tells the participant a sequence of numbers, {A1, A2, ... An}. Then the host performs a series of operations and queries on the sequence which consists:
- ADD x y D: Add D to each number in sub-sequence {Ax ... Ay}. For example, performing "ADD 2 4 1" on {1, 2, 3, 4, 5} results in {1, 3, 4, 5, 5}
- REVERSE x y: reverse the sub-sequence {Ax ... Ay}. For example, performing "REVERSE 2 4" on {1, 2, 3, 4, 5} results in {1, 4, 3, 2, 5}
- REVOLVE x y T: rotate sub-sequence {Ax ... Ay} T times. For example, performing "REVOLVE 2 4 2" on {1, 2, 3, 4, 5} results in {1, 3, 4, 2, 5}
- INSERT x P: insert P after Ax. For example, performing "INSERT 2 4" on {1, 2, 3, 4, 5} results in {1, 2, 4, 3, 4, 5}
- DELETE x: delete Ax. For example, performing "DELETE 2" on {1, 2, 3, 4, 5} results in {1, 3, 4, 5}
- MIN x y: query the participant what is the minimum number in sub-sequence {Ax ... Ay}. For example, the correct answer to "MIN 2 4" on {1, 2, 3, 4, 5} is 2
To make the show more interesting, the participant is granted a chance to turn to someone else that means when Jackson feels difficult in answering a query he may call you for help. You task is to watch the TV show and write a program giving the correct answer to each query in order to assist Jackson whenever he calls.
Input
The first line contains n (n ≤ 100000).
The following n lines describe the sequence.
Then follows M (M ≤ 100000), the numbers of operations and queries.
The following M lines describe the operations and queries.
Output
For each "MIN" query, output the correct answer.
Sample Input
5 1 2 3 4 5 2 ADD 2 4 1 MIN 4 5
Sample Output
5
Source
POJ Founder Monthly Contest – 2008.04.13, Yao Jinyu
【分析】
真实蛋疼了。。
第一次写的时候居然犯了一个傻逼到极点的错误。。。。
翻转部分不会,是看别人的。不过感觉应该还有不同的写法。
代码写得比较丑,主要是尝试了引用。
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 = 200000 + 10; 17 const int INF = 100000000; 18 const int SIZE = 450; 19 const int maxnode = 0x7fffffff + 10; 20 using namespace std; 21 typedef struct sp_node * Node; 22 struct SPLAY{ 23 struct Node{ 24 int val, Min;//分别为值,最小值,大小和lazy下标 25 int size, lazy; 26 bool turn; 27 Node *parent, *ch[2]; 28 29 //初始化 30 void NEW(int x){ 31 Min = val = x; 32 size = 1; 33 lazy = turn = 0; 34 parent = ch[0] = ch[1] = NULL; 35 } 36 int cmp(){ 37 if (parent->ch[0] == this) return 0; 38 if (parent->ch[1] == this) return 1; 39 } 40 //还是不要写在里面了.. 41 /*void pushdown(){ 42 43 } 44 void update(){ 45 size = 1; 46 if (x->ch[0] != NULL) size += x->ch[0]->size; 47 if (x->ch[1] != NULL) size += x->ch[0]->size; 48 } 49 */ 50 }mem[MAXN], *root;//mem为静态数组 51 int tot; 52 53 int get(Node *&x){return (x == NULL ? 0 : x->size);} 54 //————————————————————这一部分不能卸载里面 55 //更新 56 void update(Node *&x){ 57 if (x == NULL) return; 58 x->size = 1; 59 x->Min = x->val; 60 if (x->ch[0] != NULL) {x->Min = min(x->Min, x->ch[0]->Min);x->size += x->ch[0]->size;} 61 if (x->ch[1] != NULL) {x->Min = min(x->Min, x->ch[1]->Min);x->size += x->ch[1]->size;} 62 } 63 void pushdown(Node *&x){//标记下传 64 if (x == NULL) return; 65 if (x->lazy){ 66 int tmp = x->lazy; 67 x->val += tmp; 68 if (x->ch[0] != NULL) {x->ch[0]->lazy += tmp;x->ch[0]->Min += tmp;} 69 if (x->ch[1] != NULL) {x->ch[1]->lazy += tmp;x->ch[1]->Min += tmp;} 70 x->lazy = 0; 71 } 72 if (x->turn){//翻转 73 swap(x->ch[0], x->ch[1]);//swap内部用什么实现的呢? 74 75 if (x->ch[0] != NULL) x->ch[0]->turn ^= 1; 76 if (x->ch[1] != NULL) x->ch[1]->turn ^= 1; 77 x->turn = 0; 78 } 79 } 80 81 //———————————————————————————— 82 //旋转,1为右旋, 0为左旋 83 void Rotate(Node *&x, int d){//不用引用也可以 84 Node *y = x->parent; 85 pushdown(y);//注意顺序 86 pushdown(x); 87 pushdown(x->ch[d]);//这个不要忘了 88 89 y->ch[d ^ 1] = x->ch[d]; 90 if (x->ch[d] != NULL) x->ch[d]->parent = y; 91 x->parent = y->parent; 92 if (y->parent != NULL){ 93 if (y->parent->ch[0] == y) y->parent->ch[0] = x; 94 else y->parent->ch[1] = x; 95 } 96 x->ch[d] = y; 97 y->parent = x; 98 update(y); 99 if (y == root) root = x;//如果是引用要小心root被传下去 100 } 101 void debug(){ 102 Node *p = new Node; 103 root = new Node; 104 root->ch[1] = p; 105 p->parent = root; 106 printf("%d", p->cmp()); 107 } 108 //注意我写的这个跟下午那个不一样,下午那个好麻烦 109 void splay(Node *&x, Node *&y){ 110 pushdown(x); 111 while (x != y){ 112 if(x->parent == y){ 113 if (y->ch[0] == x) Rotate(x, 1); 114 else Rotate(x,0); 115 break; 116 }else{ 117 Node *y = x->parent, *z = y->parent;//注意一定要这样弄一下 118 if (z->ch[0] == y) 119 if (y->ch[0] == x) Rotate(y,1),Rotate(x, 1); 120 else Rotate(x, 0), Rotate(x, 1); 121 else if (y->ch[1] == x) Rotate(y, 0), Rotate(x, 0); 122 else Rotate(x, 1), Rotate(x, 0); 123 if (z == y) break; 124 } 125 update(x); 126 } 127 update(x); 128 } 129 //寻找第k大 130 void find(Node *&t, int k){ 131 int tmp; 132 Node *p = root; 133 while (1){ 134 pushdown(p); 135 tmp = get(p->ch[0]); 136 if (k == (tmp + 1)) break; 137 if (k <= tmp) p = p->ch[0]; 138 else {k -= tmp + 1, p = p->ch[1];} 139 } 140 pushdown(p); 141 splay(p, t); 142 } 143 //插入操作 144 void Insert(int pos, int val){ 145 //还是卡出来 146 find(root, pos + 1); 147 find(root->ch[1], pos + 2); 148 Node *t = &mem[tot++], *x = root->ch[1]; 149 pushdown(root); 150 pushdown(x); 151 t->NEW(val); 152 //直接拆开放中间,放在root->ch[1]->ch[0]应该也可以 153 t->ch[1] = x; 154 x->parent = t; 155 root->ch[1] = t; 156 t->parent = root; 157 splay(x, root); 158 } 159 //区间加 160 void Add(int l, int r, int x){ 161 find(root, l); 162 find(root->ch[1] , r + 2); 163 Node *t = root->ch[1]->ch[0]; 164 pushdown(t); 165 update(t); 166 t->Min += x; 167 t->lazy += x; 168 splay(t, root); 169 } 170 //翻转操作 171 void Reverse(int l, int r){ 172 find(root, l); 173 find(root->ch[1], r + 2); 174 root->ch[1]->ch[0]->turn ^= 1; 175 Node *x = root->ch[1]->ch[0]; 176 splay(x, root); 177 } 178 //交换操作,这一段我是看别人的.... 179 void Revolve(int l, int r, int t){ 180 Node *p1, *p2; 181 182 find(root, l); 183 find(root->ch[1], r + 2); 184 find(root->ch[1]->ch[0], r + 1 - t); 185 186 p1 = root->ch[1]->ch[0]; 187 pushdown(p1); 188 p2 = p1->ch[1]; 189 p1->ch[1] = NULL; 190 find(root->ch[1]->ch[0], l + 1); 191 p1 = root->ch[1]->ch[0]; 192 pushdown(p1); 193 p1->ch[0] = p2; 194 p2->parent = p1; 195 splay(p2, root); 196 } 197 int getMin(int l, int r){ 198 find(root, l); 199 find(root->ch[1], r + 2); 200 Node *x = root->ch[1]; 201 pushdown(x); 202 x = x->ch[0]; 203 pushdown(x); 204 update(x); 205 return x->Min; 206 } 207 void Erase(int pos){//删除 208 find(root, pos); 209 find(root->ch[1], pos + 2); 210 pushdown(root->ch[1]); 211 root->ch[1]->ch[0] = NULL; 212 Node *x = root->ch[1]; 213 splay(x, root); 214 } 215 void init(){ 216 //注意还要加一个正无穷 217 tot = 0; 218 root = &mem[tot++]; 219 root->NEW(INF); 220 root->ch[1] = &mem[tot++]; 221 root->ch[1]->NEW(INF); 222 } 223 void print(Node *t){ 224 if (t == NULL) return; 225 print(t->ch[0]); 226 printf("%d ", t->val); 227 if (t->parent != NULL) printf("%d\n", t->parent->val); 228 print(t->ch[1]); 229 } 230 }A; 231 232 int n, m; 233 //注意在这里为了防止掉到0,所以每个位置都要+1 234 void init(){//初始化 235 A.init(); 236 scanf("%d", &n); 237 for (int i = 0 ; i < n; i++){ 238 int x; 239 scanf("%d", &x); 240 A.Insert(i, x); 241 //printf("%d\n", A.root->val); 242 } 243 //A.print(A.root); 244 } 245 void work(){ 246 scanf("%d", &m); 247 for (int i = 1; i <= m; i++){//询问,按顺序来。。 248 char str[20]; 249 scanf("%s", str); 250 if (str[0] == ‘A‘){ 251 int l, r, x; 252 scanf("%d%d%d", &l, &r, &x); 253 A.Add(l, r, x); 254 }else if (str[0] == ‘R‘){ 255 int l, r; 256 scanf("%d%d", &l, &r); 257 if (str[3] == ‘E‘) A.Reverse(l, r); 258 else{ 259 int x, len; 260 scanf("%d", &x); 261 len = r - l + 1; 262 x = (x % len + len) % len; 263 if (x == 0 || l == r) continue;//我开始居然傻逼的写在前面.... 264 A.Revolve(l, r, x); 265 } 266 }else if (str[0] == ‘I‘){ 267 int l, x; 268 scanf("%d%d", &l, &x); 269 A.Insert(l, x); 270 }else if (str[0] == ‘D‘){ 271 int l; 272 scanf("%d", &l); 273 A.Erase(l); 274 }else if (str[0] == ‘M‘){ 275 int l, r; 276 scanf("%d%d", &l, &r); 277 printf("%d\n", A.getMin(l, r)); 278 } 279 } 280 } 281 void debug(){ 282 283 } 284 285 int main(){ 286 287 init(); 288 work(); 289 //debug(); 290 //A.debug(); 291 return 0; 292 }