POJ3580SuperMemo(无旋treap-平衡树的区间操作)
作者:互联网
题目传送门:http://poj.org/problem?id=3580
题意:有一个序列,有6种操作:
- ADD x y D:将x-y区间内的值全部加D,例如,将区间{1, 2, 3, 4, 5} 2-4 全部+1 得到 {1, 3, 4, 5, 5}
- REVERSE x y: 将x-y区间内的值全部翻转. 例如,翻转 区间 2-4,{1, 2, 3, 4, 5} 得到 {1, 4, 3, 2, 5}
- REVOLVE x y T: 将x-y区间内的值往右移动T次. 例如,将 {1, 2, 3, 4, 5} 区间2-4移动2次,得到 {1, 3, 4, 2, 5}
- INSERT x P: 在x位置后插入P. 例如,2 4 就是将 4插到2后面 操作 {1, 2, 3, 4, 5} 得到 {1, 2, 4, 3, 4, 5}
- DELETE x: 删除x位置的值. 例如,删除区间 {1, 2, 3, 4, 5} 2 位置 的值 得到 {1, 3, 4, 5}
- MIN x y: 求x - y 区间的最小值并输出,例如, 求区间 {1, 2, 3, 4, 5} 2 - 4 的 最小值 得到 2 ,并输出。
思路:没啥思路,纯纯模板题,学会了就行,不会的可以去学一下平衡树的区间操作。
代码:
1 #include<cstdio> 2 #include<cstring> 3 #include<cstdlib> 4 #include<iostream> 5 #define int long long 6 #define inf 0x3f3f3f3f 7 using namespace std; 8 const int MAXN = 1000005; 9 const int MOD = 2147483647; 10 11 struct Node 12 { 13 int left; //左子树 14 int right; //右子树 15 int size; //大小 16 int val; //值 17 int key; //平衡种子 18 int lazy; 19 int tag; 20 int mi; 21 22 }tree[MAXN]; 23 24 int Min(int x) { 25 if (x) return tree[x].mi; 26 else return inf; 27 } 28 29 int root, tot; 30 31 int add(int val) { 32 tot++; 33 tree[tot].size = 1; 34 tree[tot].val = val; 35 tree[tot].key = rand() % MOD; 36 tree[tot].left = 0; 37 tree[tot].right = 0; 38 tree[tot].mi = val; 39 40 return tot; 41 } 42 43 void update_root(int now) { 44 int left, right; 45 46 left = tree[now].left; 47 right = tree[now].right; 48 49 tree[now].size = tree[left].size + tree[right].size + 1; 50 /*if (left != 0 || right != 0) { 51 if (left != 0) tree[now].mi = min(tree[now].val, tree[left].mi); 52 else if (right != 0) tree[now].mi = min(tree[now].val, tree[right].mi); 53 else if (left != 0 && right != 0) tree[now].mi = min(tree[now].val, min(tree[left].mi, tree[right].mi)); 54 } 55 else tree[now].mi = tree[now].val;*/ 56 //tree[now].mi = min(tree[left].mi, tree[right].mi); 57 58 tree[now].mi = min(tree[now].val, min(Min(left), Min(right))); 59 } 60 61 void pushdown(int x) { 62 if (tree[x].lazy) { 63 tree[tree[x].left].val += tree[x].lazy; 64 tree[tree[x].right].val += tree[x].lazy; 65 66 tree[tree[x].left].mi += tree[x].lazy; 67 tree[tree[x].right].mi += tree[x].lazy; 68 69 tree[tree[x].left].lazy += tree[x].lazy; 70 tree[tree[x].right].lazy += tree[x].lazy; 71 tree[x].lazy = 0; 72 } 73 if (tree[x].tag) { 74 tree[tree[x].left].tag ^= 1; 75 tree[tree[x].right].tag ^= 1; 76 swap(tree[x].left, tree[x].right); 77 tree[x].tag ^= 1; 78 } 79 } 80 81 //拆分(now原treap,a左子树,b右子树,val值) 82 void split_val(int now, int& a, int& b, int val) { 83 if (now == 0) { 84 a = 0; 85 b = 0; 86 return; 87 } 88 89 if (tree[now].val <= val) {//now左子树中的所有值都小于now, 90 a = now; 91 split_val(tree[now].right, tree[a].right, b, val); 92 } 93 else { 94 b = now; 95 split_val(tree[now].left, a, tree[b].left, val); 96 } 97 98 update_root(now); 99 } 100 101 102 void split_k(int now, int& a, int& b, int k) { 103 if (now == 0) { 104 a = 0; 105 b = 0; 106 return; 107 } 108 pushdown(now); 109 if (tree[tree[now].left].size < k) { 110 a = now; 111 split_k(tree[now].right, tree[a].right, b, k - tree[tree[now].left].size - 1); 112 } 113 else { 114 b = now; 115 split_k(tree[now].left, a, tree[b].left, k); 116 } 117 118 update_root(now); 119 } 120 121 void merge_new(int& now, int a, int b) { 122 if (a == 0 || b == 0) { 123 now = a + b; 124 return; 125 } 126 pushdown(a), pushdown(b); 127 //按照key值合并(堆性质) 128 if (tree[a].key < tree[b].key) { 129 /** 130 * a树key值小于b树,那么b树属于a树的后代,因为b树恒大于a树,那么b树一定属于a树的右后代, 131 * a的左子树不变,直接赋给now,递归合并a的右子树和b 132 */ 133 now = a; 134 merge_new(tree[now].right, tree[a].right, b); 135 } 136 else { 137 now = b; 138 merge_new(tree[now].left, a, tree[b].left); 139 } 140 141 update_root(now); 142 } 143 144 void find_new(int now, int rank) {//找第k大 145 while (tree[tree[now].left].size + 1 != rank) { 146 if (tree[tree[now].left].size >= rank) { 147 now = tree[now].left; 148 } 149 else { 150 rank -= tree[tree[now].left].size + 1; 151 now = tree[now].right; 152 } 153 } 154 cout << tree[now].val << "\n"; 155 } 156 157 void insert_new(int val) { 158 int x, y, z; 159 160 x = 0; 161 y = 0; 162 z = add(val); 163 split_val(root, x, y, val); 164 merge_new(x, x, z); 165 merge_new(root, x, y); 166 } 167 168 void insert(int pos, int val) { 169 int x, y, z; 170 171 x = 0; 172 y = 0; 173 z = add(val); 174 //split_val(root, x, y, pos); 175 split_k(root, x, y, pos); 176 merge_new(x, x, z); 177 merge_new(root, x, y); 178 } 179 180 void del_new(int pos) { 181 int x, y, z; 182 183 x = y = z = 0; 184 /*split_val(root, x, y, val); 185 split_val(x, x, z, val - 1);*/ 186 split_k(root, x, y, pos); 187 split_k(x, x, z, pos - 1); 188 merge_new(z, tree[z].left, tree[z].right); 189 merge_new(x, x, z); 190 merge_new(root, x, y); 191 } 192 193 void get_rank(int val) { 194 int x, y; 195 196 x = y = 0; 197 split_val(root, x, y, val - 1); 198 cout << tree[x].size + 1 << "\n"; 199 merge_new(root, x, y); 200 } 201 202 void get_val(int rank) { 203 find_new(root, rank); 204 } 205 206 void get_pre(int val) { 207 int x, y; 208 209 x = y = 0; 210 split_val(root, x, y, val - 1); 211 find_new(x, tree[x].size); 212 merge_new(root, x, y); 213 } 214 215 void get_next(int val) { 216 int x, y; 217 218 x = y = 0; 219 split_val(root, x, y, val); 220 find_new(y, 1); 221 merge_new(root, x, y); 222 } 223 224 void reverse(int l, int r) { 225 int a, b, c, d; 226 split_k(root, a, b, r); 227 split_k(a, c, d, l - 1); 228 tree[d].tag ^= 1; 229 int rt; 230 merge_new(rt, c, d); 231 merge_new(root, rt, b); 232 } 233 234 void revolve(int l, int r, int t) { 235 int len = r - l + 1; 236 int a, b, c, d, e, f; 237 t = (t % len + len) % len; 238 if (t == 0) return; 239 split_k(root, a, b, r); 240 split_k(a, c, d, l - 1); 241 split_k(d, e, f, len - t); 242 int rt1; 243 merge_new(rt1, c, f); 244 int rt2; 245 merge_new(rt2, rt1, e); 246 merge_new(root, rt2, b); 247 } 248 249 void update(int l, int r, int w) { 250 int a, b, c, d; 251 split_k(root, a, b, r); 252 split_k(a, c, d, l - 1); 253 tree[d].lazy += w; 254 tree[d].val += w; 255 tree[d].mi += w; 256 int rt; 257 merge_new(rt, c, d); 258 merge_new(root, rt, b); 259 260 } 261 262 void get_min(int l, int r) { 263 int a, b, c, d; 264 split_k(root, a, b, r); 265 split_k(a, c, d, l - 1); 266 pushdown(d); 267 cout << tree[d].mi << "\n"; 268 int rt; 269 merge_new(rt, c, d); 270 merge_new(root, rt, b); 271 } 272 273 int n, m; 274 int cnt = 1; 275 int flag = 0; 276 277 void print(int x) { 278 if (!x)return; 279 pushdown(x); 280 print(tree[x].left); 281 //if (tree[x].val != MOD) cout << tree[x].val << " " ; 282 print(tree[x].right); 283 } 284 285 signed main() { 286 287 ios::sync_with_stdio(false); 288 cin.tie(0); 289 290 //int n, m; 291 cin >> n; 292 293 memset(tree, 0, sizeof(tree)); 294 295 add(MOD); 296 root = 1; 297 tree[root].size = 0; 298 299 int x; 300 for (int i = 1; i <= n; i++) { 301 cin >> x; 302 insert(i - 1, x); 303 } 304 //get_min(1, n); 305 //revolve(2, 4, 2); 306 print(root); 307 //cout << "\n"; 308 cin >> m; 309 for (; m; --m) { 310 string s; 311 cin >> s; 312 int x, y, val; 313 if (s[0] == 'A') { 314 cin >> x >> y >> val; 315 update(x, y, val); 316 //print(root); 317 //cout << "\n"; 318 } 319 else if (s[0] == 'R' && s[3] == 'E') { 320 cin >> x >> y; 321 reverse(x, y); 322 //print(root); 323 ///cout << "\n"; 324 } 325 else if (s[0] == 'R' && s[3] == 'O') { 326 cin >> x >> y >> val; 327 revolve(x, y, val); 328 //print(root); 329 //cout << "\n"; 330 } 331 else if (s[0] == 'I') { 332 cin >> x >> y; 333 insert(x, y); 334 //print(root); 335 //cout << "\n"; 336 } 337 else if (s[0] == 'D') { 338 cin >> x; 339 del_new(x); 340 //print(root); 341 //cout << "\n"; 342 } 343 else { 344 cin >> x >> y; 345 get_min(x, y); 346 //print(root); 347 //cout << "\n"; 348 } 349 } 350 /*update(1, n, 1); 351 reverse(1, n);*/ 352 //print(root); 353 //for (; m; --m) { 354 // int x, y; 355 // cin >> x >> y; 356 // reverse(x, y); 357 // //print(root); 358 //} 359 //print(root); 360 //cout << "\n"; 361 362 return 0; 363 }
标签:right,val,int,无旋,tree,treap,POJ3580SuperMemo,now,left 来源: https://www.cnblogs.com/wabi/p/16514176.html