【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

POJ Founder Monthly Contest – 2008.04.13, Yao Jinyu

【分析】

真实蛋疼了。。

第一次写的时候居然犯了一个傻逼到极点的错误。。。。

翻转部分不会,是看别人的。不过感觉应该还有不同的写法。

代码写得比较丑,主要是尝试了引用。

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

时间: 2024-11-05 11:51:54

【POJ3580】【splay版】SuperMemo的相关文章

bzoj1861 书架 splay版

单点插入删除以及求前缀 #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int M=100055,inf=1000000000; int read(){ int ans=0,f=1,c=getchar(); while(c<'0'||c>'9'){if(c=='-') f=-1; c=getchar();} while(c>='0'&am

[P3369]普通平衡树(Splay版)

模板,不解释 #include<bits/stdc++.h> using namespace std; const int mxn=1e5+5; int fa[mxn],ch[mxn][2],sz[mxn],cnt[mxn],val[mxn],rt,tot; namespace Splay { void push_up(int x) { sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+cnt[x]; }; void rotate(int x) { int y=fa[x],z=f

数列[专杀Splay版]

时间限制: 3 Sec  内存限制: 128 MB提交: 49  解决: 7 题目描述 输入一个数列,你需要进行如下操作: 1. 把编号为I的数值改为K 2. 输出从小到大排序后第k个数 输入 输入文件第一行包含两个整数N.M,分别表示数列长度与操作个数. 第二行有N个整数,为初始数列中的N个整数. 接下来M行每行如果只有一个整数k,那么就是输出第k小数,否则两个整数I,K表示把第I个数的数值改为K. 输出 输出所有要求输出的数,每个数单独一行. 样例输入 5 3 5 3 2 1 1 4 2 6

洛谷P3391 【模板】文艺平衡树(Splay)

题目背景 这是一道经典的Splay模板题——文艺平衡树. 题目描述 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1 输入输出格式 输入格式: 第一行为n,m n表示初始序列有n个数,这个序列依次是(1,2, \cdots n-1,n)(1,2,?n−1,n) m表示翻转操作次数 接下来m行每行两个数 [l,r][l,r] 数据保证 1 \leq l \leq r

日总结——20180303

上午在打zroi的比赛,然而菜得只会T1,虽然是50分的O(n2)写法,大概就是维护一个前缀和,后缀max以及max值,这三个都是用n2的时间进行更新的,最后求值的时候也是n2的,好像线段树维护一下就可以AC了,不是很清楚,出了成绩再说吧 下午打了打cp的比赛,发现自己什么都不会,弃疗之后手玩提答,AC之后就没时间了 晚上继续学splay,终于敲出来了splay版的普通平衡树,过程中模板敲错n次,真实彩笔 这里给出详细注释的板子: 1 //普通平衡树 2 #include<iostream>

GSS1 ~ 8解题报告 【完整版】

GSS1 -- GSS8 简述做法加代码. GSS1 给出了序列\(A[1]\),\(A[2]\),-,\(A[N]\). \((a[i]≤15007,1≤N≤50000)\).查询定义如下: 查询\((x,y)=max\{a[i]+a[i+1]+...+a[j];x≤i≤j≤y\}\). 给定M个查询,程序必须输出这些查询的结果. 思路: 我们维护四个值: sum, lsum, rsum, msum 然后进行更新,静态查询即可. 具体讲解见 这里了啦 code: #include <algor

又一道Splay吐血题 [POJ 3580] SuperMemo

SuperMemo Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 9878   Accepted: 3177 Case Time Limit: 2000MS Description Your friend, Jackson is invited to a TV show called SuperMemo in which the participant is told to play a memorizing game.

POJ 3580 SuperMemo (Splay 区间更新、翻转、循环右移,插入,删除,查询)

SuperMemo Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 13917   Accepted: 4352 Case Time Limit: 2000MS Description Your friend, Jackson is invited to a TV show called SuperMemo in which the participant is told to play a memorizing game

poj3580 SuperMemo

SuperMemo Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 12273   Accepted: 3887 Case Time Limit: 2000MS Description Your friend, Jackson is invited to a TV show called SuperMemo in which the participant is told to play a memorizing game