ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

POJ3580SuperMemo(无旋treap-平衡树的区间操作)

2022-07-24 11:31:24  阅读:146  来源: 互联网

标签:right val int 无旋 tree treap POJ3580SuperMemo now left


题目传送门:http://poj.org/problem?id=3580

题意:有一个序列,有6种操作:

  1. ADD x y D:将x-y区间内的值全部加D,例如,将区间{1, 2, 3, 4, 5} 2-4 全部+1 得到 {1, 3, 4, 5, 5}
  2. REVERSE x y: 将x-y区间内的值全部翻转. 例如,翻转 区间 2-4,{1, 2, 3, 4, 5} 得到 {1, 4, 3, 2, 5}
  3. REVOLVE x y T: 将x-y区间内的值往右移动T次. 例如,将 {1, 2, 3, 4, 5} 区间2-4移动2次,得到 {1, 3, 4, 2, 5}
  4. INSERT x P: 在x位置后插入P. 例如,2 4 就是将 4插到2后面 操作 {1, 2, 3, 4, 5} 得到 {1, 2, 4, 3, 4, 5}
  5. DELETE x: 删除x位置的值. 例如,删除区间 {1, 2, 3, 4, 5}  2   位置 的值 得到   {1, 3, 4, 5}
  6. 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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有