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