其他分享
首页 > 其他分享> > POJ3580SuperMemo(无旋treap-平衡树的区间操作)

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

作者:互联网

题目传送门: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