【POJ3580】【splay版】SuperMemo

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, {A1A2, ... An}. Then the host performs a series of operations and queries on the sequence which consists:

  1. 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}
  2. 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}
  3. REVOLVE x y T: rotate sub-sequence {Ax ... AyT times. For example, performing "REVOLVE 2 4 2" on {1, 2, 3, 4, 5} results in {1, 3, 4, 2, 5}
  4. 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}
  5. DELETE x: delete Ax. For example, performing "DELETE 2" on {1, 2, 3, 4, 5} results in {1, 3, 4, 5}
  6. 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 (≤ 100000).

The following n lines describe the sequence.

Then follows 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

【分析】
真实蛋疼了。。
第一次写的时候居然犯了一个傻逼到极点的错误。。。。
翻转部分不会,是看别人的。不过感觉应该还有不同的写法。
代码写得比较丑,主要是尝试了引用。
  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 struct SPLAY{
 22        struct Node{
 23               int val, Min;//分别为值,最小值,大小和lazy下标 
 24               int size, lazy;
 25               bool turn;
 26               Node *parent, *ch[2];
 27               
 28               //初始化 
 29               void NEW(int x){
 30                    Min = val = x;
 31                    size = 1;
 32                    lazy = turn = 0;
 33                    parent = ch[0] = ch[1] = NULL;
 34               }
 35               int cmp(){
 36                   if (parent->ch[0] == this) return 0;
 37                   if (parent->ch[1] == this) return 1;
 38               }
 39               //还是不要写在里面了..
 40               /*void pushdown(){
 41                    
 42               } 
 43               void update(){
 44                    size = 1;
 45                    if (x->ch[0] != NULL) size += x->ch[0]->size;
 46                    if (x->ch[1] != NULL) size += x->ch[0]->size;
 47               }     
 48               */    
 49        }mem[MAXN], *root;//mem为静态数组 
 50        int tot;
 51        
 52        int get(Node *&x){return (x == NULL ? 0 : x->size);}
 53        //————————————————————这一部分不能卸载里面 
 54        //更新 
 55        void update(Node *&x){
 56             if (x == NULL) return;
 57             x->size = 1;
 58             x->Min = x->val;
 59             if (x->ch[0] != NULL) {x->Min = min(x->Min, x->ch[0]->Min);x->size += x->ch[0]->size;}
 60             if (x->ch[1] != NULL) {x->Min = min(x->Min, x->ch[1]->Min);x->size += x->ch[1]->size;}
 61        }
 62        void pushdown(Node *&x){//标记下传 
 63             if (x == NULL) return;
 64             if (x->lazy){
 65                int tmp = x->lazy;
 66                x->val += tmp;
 67                if (x->ch[0] != NULL) {x->ch[0]->lazy += tmp;x->ch[0]->Min += tmp;}
 68                if (x->ch[1] != NULL) {x->ch[1]->lazy += tmp;x->ch[1]->Min += tmp;}
 69                x->lazy = 0;
 70             } 
 71             if (x->turn){//翻转
 72                swap(x->ch[0], x->ch[1]);//swap内部用什么实现的呢? 
 73                
 74                if (x->ch[0] != NULL) x->ch[0]->turn ^= 1;
 75                if (x->ch[1] != NULL) x->ch[1]->turn ^= 1; 
 76                x->turn = 0;
 77             }
 78        }
 79        
 80        //———————————————————————————— 
 81        //旋转,1为右旋, 0为左旋
 82        void Rotate(Node *&x, int d){//不用引用也可以 
 83             Node *y = x->parent;
 84             pushdown(y);//注意顺序 
 85             pushdown(x);
 86             pushdown(x->ch[d]);//这个不要忘了
 87             
 88             y->ch[d ^ 1] = x->ch[d];
 89             if (x->ch[d] != NULL) x->ch[d]->parent = y;
 90             x->parent = y->parent;
 91             if (y->parent != NULL){
 92                if (y->parent->ch[0] == y) y->parent->ch[0] = x;
 93                else y->parent->ch[1] = x;
 94             } 
 95             x->ch[d] = y;
 96             y->parent = x;
 97             update(y);
 98             if (y == root) root = x;//如果是引用要小心root被传下去 
 99        } 
100        void debug(){
101             Node *p = new Node;
102             root = new Node;
103             root->ch[1] = p;
104             p->parent = root;
105             printf("%d", p->cmp());
106        }
107        //注意我写的这个跟下午那个不一样,下午那个好麻烦 
108        void splay(Node *&x, Node *&y){
109             pushdown(x);
110             while (x != y){
111                   if(x->parent == y){
112                             if (y->ch[0] == x) Rotate(x, 1);
113                             else Rotate(x,0);
114                             break;
115                   }else{
116                             Node *y = x->parent, *z = y->parent;//注意一定要这样弄一下 
117                             if (z->ch[0] == y)
118                             if (y->ch[0] == x) Rotate(y,1),Rotate(x, 1);
119                             else Rotate(x, 0), Rotate(x, 1); 
120                             else if (y->ch[1] == x) Rotate(y, 0), Rotate(x, 0); 
121                             else Rotate(x, 1), Rotate(x, 0); 
122                             if (z == y) break;
123                   }
124                   update(x);
125             }
126             update(x);
127        }
128        //寻找第k大 
129        void find(Node *&t, int k){
130             int tmp;
131             Node *p = root;
132             while (1){
133                   pushdown(p);
134                   tmp = get(p->ch[0]);
135                   if (k == (tmp + 1)) break;
136                   if (k <= tmp) p = p->ch[0];
137                   else {k -= tmp + 1, p = p->ch[1];}
138             }
139             pushdown(p);
140             splay(p, t);
141        }
142        //插入操作 
143        void Insert(int pos, int val){
144             //还是卡出来 
145             find(root, pos + 1);
146             find(root->ch[1], pos + 2);
147             Node *t = &mem[tot++], *x = root->ch[1];
148             pushdown(root);
149             pushdown(x);
150             t->NEW(val);
151             //直接拆开放中间,放在root->ch[1]->ch[0]应该也可以 
152             t->ch[1] = x;
153             x->parent = t;
154             root->ch[1] = t;
155             t->parent = root;
156             splay(x, root);
157        }
158        //区间加 
159        void Add(int l, int r, int x){
160             find(root, l);
161             find(root->ch[1] , r + 2);
162             Node *t = root->ch[1]->ch[0];
163             pushdown(t);
164             update(t);
165             t->Min += x;
166             t->lazy += x;
167             splay(t, root);
168        }
169        //翻转操作 
170        void Reverse(int l, int r){
171             find(root, l);
172             find(root->ch[1], r + 2);
173             root->ch[1]->ch[0]->turn ^= 1;
174             Node *x = root->ch[1]->ch[0];
175             splay(x, root);
176        }
177        //交换操作,这一段我是看别人的.... 
178        void Revolve(int l, int r, int t){
179             Node *p1, *p2;
180             
181             find(root, l);
182             find(root->ch[1], r + 2);
183             find(root->ch[1]->ch[0], r + 1 - t);
184             
185             p1 = root->ch[1]->ch[0];
186             pushdown(p1);
187             p2 = p1->ch[1];
188             p1->ch[1] = NULL;
189             find(root->ch[1]->ch[0], l + 1);
190             p1 = root->ch[1]->ch[0];
191             pushdown(p1);
192             p1->ch[0] = p2;
193             p2->parent = p1;
194             splay(p2, root);
195        }
196        int getMin(int l, int r){
197             find(root, l);
198             find(root->ch[1], r + 2);
199             Node *x = root->ch[1];
200             pushdown(x);
201             x = x->ch[0];
202             pushdown(x);
203             update(x);
204             return x->Min; 
205        }
206        void Erase(int pos){//删除 
207             find(root, pos);
208             find(root->ch[1], pos + 2);
209             pushdown(root->ch[1]);
210             root->ch[1]->ch[0] = NULL;
211             Node *x = root->ch[1];
212             splay(x, root);
213        }
214        void init(){
215             //注意还要加一个正无穷 
216             tot = 0;
217             root = &mem[tot++];
218             root->NEW(INF);
219             root->ch[1] = &mem[tot++];
220             root->ch[1]->NEW(INF);
221        }
222        void print(Node *t){
223             if (t == NULL) return;
224             print(t->ch[0]);
225             printf("%d ", t->val);
226             if (t->parent != NULL) printf("%d
", t->parent->val);
227             print(t->ch[1]);
228        }
229 }A;
230 
231 int n, m;
232 //注意在这里为了防止掉到0,所以每个位置都要+1 
233 void init(){//初始化 
234     A.init();
235     scanf("%d", &n);
236     for (int i = 0 ; i < n; i++){
237         int x;
238         scanf("%d", &x);
239         A.Insert(i, x);
240         //printf("%d
", A.root->val);
241     }
242     //A.print(A.root);
243 }
244 void work(){
245      scanf("%d", &m);
246      for (int i = 1; i <= m; i++){//询问,按顺序来。。 
247            char str[20];
248            scanf("%s", str);
249            if (str[0] == 'A'){
250               int l, r, x;
251               scanf("%d%d%d", &l, &r, &x);
252               A.Add(l, r, x);
253            }else if (str[0] == 'R'){
254               int l, r;
255               scanf("%d%d", &l, &r);
256               if (str[3] == 'E') A.Reverse(l, r);
257               else{
258                    int x, len;
259                    scanf("%d", &x);
260                    len = r - l + 1;
261                    x = (x % len + len) % len;
262                    if (x == 0 || l == r) continue;//我开始居然傻逼的写在前面.... 
263                    A.Revolve(l, r, x);
264               } 
265            }else if (str[0] == 'I'){
266                  int l, x; 
267                  scanf("%d%d", &l, &x);
268                  A.Insert(l, x);
269            }else if (str[0] == 'D'){
270                  int l;
271                  scanf("%d", &l);
272                  A.Erase(l);
273            }else if (str[0] == 'M'){
274                  int l, r;
275                  scanf("%d%d", &l, &r);
276                  printf("%d
", A.getMin(l, r));
277            }
278      }
279 }
280 void debug(){
281      
282 }
283 
284 int main(){
285     
286     init();
287     work();
288     //debug();
289     //A.debug();
290     return 0;
291 }
View Code
原文地址:https://www.cnblogs.com/hoskey/p/4331221.html