POJ 3580 SuperMemo (Splay)
来源:互联网 发布:电力电子技术知乎 编辑:程序博客网 时间:2024/05/24 15:37
思路:
区间的一系列操作, 还有翻转什么的,显然Splay
主要说一下 那个循环右移的操作吧
次数先对总长度取模, 因为相当于有循环节。
然后 这个操作 相当于 把一个区间分成两个子区间, 把后面挪到前面。
假设两个区间是 [s1, e1]和 [s2, e2]
那么先把s2-1 转到根, e2+1 转到根的下面, 将e2转到e2+1的下面,将 e2+1的左子树 切下来。
这样就把后一个区间拿出来了, 同样的操作 将s1-1转到根, s1 转到根的下面, 插到 s1左子树即可。
#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int maxn = 200000 + 10;int n, m;int num[maxn];const int inf = 0x3f3f3f3f;struct SplayTree{ void Rotate(int x, int f){ int y = pre[x], z = pre[y]; pushdown(x); pushdown(y); ch[y][!f] = ch[x][f]; pre[ch[x][f] ] = y; ch[x][f] = y; pre[y] = x; pre[x] = z; if (pre[x]) ch[z][ch[z][1] == y ] = x; pushup(y); } void Splay(int x,int goal){ pushdown(x); while(pre[x] != goal){ if (pre[pre[x] ] == goal){ Rotate(x, ch[pre[x] ][0] == x); } else { int y = pre[x], z = pre[y]; int f = (ch[z][0] == y); if (ch[y][f] == x) Rotate(x, !f), Rotate(x, f); else Rotate(y, f), Rotate(x, f); } } pushup(x); if (goal == 0) root = x; } void RotateTo(int k,int goal){ int x = root; pushdown(x); while(sz[ ch[x][0] ] != k){ if (k < sz[ ch[x][0] ]){ x = ch[x][0]; } else { k -= (sz[ ch[x][0] ] + 1); x = ch[x][1]; } pushdown(x); } Splay(x, goal); } void clear(){ ch[0][0] = ch[0][1] = pre[0] = sz[0] = 0; top = 0; root = n = 0; val[0] = -inf; Min[0] = inf; rev[0] = 0; add[0] = 0; NewNode(root, -inf); NewNode(ch[root][1], inf); pre[n] = root; sz[root] = 2; } void NewNode(int& x,int c){ if (top) x = pool[--top]; else x = ++n; ch[x][0] = ch[x][1] = pre[x] = 0; sz[x] = 1; val[x] = Min[x] = c; } void pushup(int x){ sz[x] = 1 + sz[ch[x][0] ] + sz[ch[x][1] ]; Min[x] = min(val[x] , min(Min[ch[x][0] ] , Min[ch[x][1] ])); } void pushdown(int x){ if (rev[x]){ update_rev(ch[x][0]); update_rev(ch[x][1]); rev[x] = 0; } if (add[x]){ update_add(ch[x][0], add[x]); update_add(ch[x][1], add[x]); add[x] = 0; } } void init(int pos, int tot){ clear(); cnt = tot; RotateTo(pos, 0); RotateTo(pos + 1, root); build(ch[ ch[root][1] ][0], 1, tot, ch[root][1]); pushup(ch[root][1]); pushup(root); } void build(int& x,int l,int r,int f){ if (l > r) return ; int mid = (l + r) >> 1; NewNode(x, num[mid]); build(ch[x][0],l, mid-1, x); build(ch[x][1], mid+1, r, x); pre[x] = f; pushup(x); } void update_add(int x,int v){ if (!x) return; val[x] += v; Min[x] += v; add[x] += v; } void update_rev(int x){ if (!x) return; swap(ch[x][0], ch[x][1]); rev[x] ^= 1; } void ADD(int l,int r,int c){ RotateTo(l - 1, 0); RotateTo(r + 1, root); int key = ch[ch[root][1] ][0]; update_add(key, c); pushup(ch[root][1]); pushup(root); } int getmin(int l,int r){ RotateTo(l-1,0); RotateTo(r+1,root); int key = ch[ch[root][1] ][0]; return Min[key]; } void reverse(int l, int r){ RotateTo(l-1, 0); RotateTo(r + 1, root); int key = ch[ ch[root][1] ][0]; update_rev(key); } void erase(int x){ if (!x) return; pool[top++] = x; erase(ch[x][0]); erase(ch[x][1]); } void del(int x){ RotateTo(x-1, 0); RotateTo(x+1, root); int key = ch[ ch[root][1] ][0]; ch[ ch[root][1] ][0] = 0; cnt -= sz[key]; erase(key); pushup(ch[root][1]); pushup(root); } void insert(int pos, int v){ cnt++; RotateTo(pos, 0); RotateTo(pos + 1, root); num[1] = v; build(ch[ ch[root][1] ][0], 1, 1, ch[root][1]); pushup(ch[root][1]); pushup(root); } void revolve(int x, int y, int t){ t %= (y-x+1); if (t < 0) t = y - x + 1 + t; if (t == 0) return; int s2 = y - t + 1, e2 = y; int s1 = x, e1 = s2 - 1; RotateTo(s2 - 1, 0); RotateTo(e2 + 1, root); int haha = ch[root][1]; RotateTo(e2, haha); int key = ch[ ch[root][1] ][0]; pre[key] = 0; ch[ch[root][1] ][0] = 0; pushup(ch[root][1]); pushup(root); RotateTo(s1 - 1, 0); RotateTo(s1, root); ch[ch[root][1] ][0] = key; pre[key] = ch[root][1]; pushup(ch[root][1]); pushup(root); } int root, n, cnt, ct, top; int ch[maxn][2]; int pre[maxn]; int sz[maxn]; int val[maxn]; int Min[maxn]; int add[maxn]; int pool[maxn]; int rev[maxn];}spt;int main(){ int n; scanf("%d",&n); for (int i = 1; i <= n; ++i){ scanf("%d", &num[i]); } int q; spt.init(0, n); scanf("%d", &q); char op[10]; while(q--){ scanf("%s", op); if (op[0] == 'A'){ int x, y, d; scanf("%d %d %d",&x, &y, &d); spt.ADD(x, y, d); } else if (op[0] == 'R'){ if (op[3] == 'E'){ int x, y; scanf("%d %d",&x, &y); spt.reverse(x, y); } else { int x, y, t; scanf("%d %d %d", &x, &y, &t); spt.revolve(x, y, t); } } else if (op[0] == 'I'){ int x, p; scanf("%d %d",&x, &p); spt.insert(x, p); } else if (op[0] == 'D'){ int x; scanf("%d", &x); spt.del(x); } else { int x, y; scanf("%d %d", &x, &y); printf("%d\n", spt.getmin(x, y)); } } return 0;}
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, {A1, A2, ... An}. Then the host performs a series of operations and queries on the sequence which consists:
- 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}
- 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}
- REVOLVE x y T: rotate sub-sequence {Ax ... Ay} T times. For example, performing "REVOLVE 2 4 2" on {1, 2, 3, 4, 5} results in {1, 3, 4, 2, 5}
- 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}
- DELETE x: delete Ax. For example, performing "DELETE 2" on {1, 2, 3, 4, 5} results in {1, 3, 4, 5}
- 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 n (n ≤ 100000).
The following n lines describe the sequence.
Then follows M (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
51 2 3 4 52ADD 2 4 1MIN 4 5
Sample Output
5
Source
[Submit] [Go Back] [Status] [Discuss]
- POJ 3580 SuperMemo (Splay)
- splay POJ 3580SuperMemo
- POJ 3580 SuperMemo(Splay)
- POJ 3580 SuperMemo(Splay)
- poj 3580 SuperMemo(Splay)
- poj-3580-SuperMemo-splay
- 【POJ】3580 SuperMemo 【splay】
- POJ 3580 SuperMemo Splay
- POJ 3580 SuperMemo [Splay]
- POJ-3580 SuperMemo(Splay树)
- POJ 3580 SuperMemo(Splay树)
- BZOJ 1895 & POJ 3580 supermemo (splay)
- POJ 3580 SuperMemo (Splay tree)
- POJ 3580 SuperMemo (SPLAY TREE)
- 【splay tree】 POJ 3580 SuperMemo
- POJ 3580 SuperMemo(Splay模板)
- poj-3580 SuperMemo[splay tree]
- POJ 3580——SuperMemo(Splay树,经典题)
- Go语言备忘录:反射的原理与使用详解
- 最大子数组—Lintcode
- Jmeter特殊情况一:登录请求中密码加密的情况
- Android 側滑返回上一個Activity
- Redis 讲解系列之 Redis的事务
- POJ 3580 SuperMemo (Splay)
- UVA-11093 Just Finish it up
- Nginx的启动、停止与重启
- 内存问题的排查工具和方法– Clang的AddressSanitizer
- 几种磁盘阵列技术
- 2017.10.12 内存管理
- 把 Nginx 创建为 Windows 的一个服务
- Excel Sheet Column Number:有字母组成的26进制转换成10进制
- Caused by: java.lang.IllegalArgumentException: Parameter with that position [1] did not exist