POJ 3580 SuperMemo(Splay树)

来源:互联网 发布:2017dnf商人起步必知 编辑:程序博客网 时间:2024/05/21 03:26

SuperMemo
Time Limit: 5000MS Memory Limit: 65536KTotal Submissions: 16499 Accepted: 5203Case 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. 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

51 2 3 4 52ADD 2 4 1MIN 4 5

Sample Output

5

Source

POJ Founder Monthly Contest – 2008.04.13, Yao Jinyu

题意:

add x,y D:第x个数到第y个数之间的数每个加D;

reverse x y:第x个数到第y个数之间全部数翻转;

revolve x y T:第x个数到第y个数之间的数,向后循环流动T次,即后面T个数变成这段子序列的最前面T个,前面的被挤到后面。

insert x P:在第x个数后面插入一个数P。

delete x:删除第x个数。

min x,y:求第x个数到第y个数之间的最小数字。


代码:

#include <cstdio>#include <cmath>#include <algorithm>using namespace std;typedef long long LL;const LL INF = 1e18;const int maxn = 200005;int a[maxn];int ch[maxn][2], fa[maxn];int sz[maxn], rev[maxn];LL val[maxn], sum[maxn], add[maxn], Min[maxn];int tol, rt;void newNode(int p, int __val, int __fa){    val[p] = __val;    sum[p] = __val;    Min[p] = __val;    fa[p] = __fa;    sz[p] = 1;    rev[p] = add[p] = 0;    ch[p][0] = ch[p][1] = 0;}void mark_add(int p, LL __add){    add[p] += __add;    val[p] += __add;    sum[p] += __add * sz[p];    Min[p] += __add;}void mark_rev(int p){    rev[p] ^= 1;    swap(ch[p][0], ch[p][1]);}void push_down(int p){    if(rev[p]){        mark_rev(ch[p][0]);        mark_rev(ch[p][1]);        rev[p] = 0;    }    if(add[p]){        mark_add(ch[p][0], add[p]);        mark_add(ch[p][1], add[p]);        add[p] = 0;    }}void push_up(int p){    int ls = ch[p][0], rs = ch[p][1];    sz[p] = sz[ls] + sz[rs] + 1;    sum[p] = sum[ls] + sum[rs] + val[p];    Min[p] = min(val[p], min(Min[ls], Min[rs]));}void Rotate(int x, int t){    int p = fa[x];    push_down(p);    push_down(x);    fa[x] = fa[p];    if(fa[p])        ch[fa[p]][ch[fa[p]][1] == p] = x;    ch[p][!t] = ch[x][t];    if(ch[x][t])        fa[ch[x][t]] = p;    ch[x][t] = p;    fa[p] = x;    push_up(p);}void splay(int x, int y){    if(!x) return;    push_down(x);    while(fa[x] != y){        int p = fa[x];        if(fa[p] == y){            push_down(p);            push_down(x);            Rotate(x, ch[p][0] == x);        }else{           int g = fa[p];           push_down(g);           push_down(p);           push_down(x);           if(ch[g][0] == p){                if(ch[p][0] == x){                    Rotate(p, 1);                    Rotate(x, 1);                }else{                    Rotate(x, 0);                    Rotate(x, 1);                }           }else{                if(ch[p][1] == x){                    Rotate(p, 0);                    Rotate(x, 0);                }else{                    Rotate(x, 1);                    Rotate(x, 0);                }           }        }    }    push_up(x);    if(!y) rt = x;}int build(int l, int r, int fa){    if(l > r) return 0;    int mid = (l + r) >> 1;    newNode(mid, a[mid], fa);    ch[mid][0] = build(l, mid - 1, mid);    ch[mid][1] = build(mid + 1, r, mid);    push_up(mid);    return mid;}int get_pos(int k){    int p = rt;    while(1){        push_down(p);        if(sz[ch[p][0]] >= k)            p = ch[p][0];        else if(sz[ch[p][0]] + 1 == k)            break;        else{            k -= sz[ch[p][0]] + 1;            p = ch[p][1];        }    }    return p;}void Add(int a, int b, int c){    int pre = get_pos(a - 1);    int nxt = get_pos(b + 1);    splay(pre, 0);    splay(nxt, pre);    mark_add(ch[nxt][0], c);    push_up(nxt);    push_up(pre);}void Rev(int a, int b){    int pre = get_pos(a - 1);    int nxt = get_pos(b + 1);    splay(pre, 0);    splay(nxt, pre);    mark_rev(ch[nxt][0]);    push_up(nxt);    push_up(pre);}void Ins(int x, int P){    int nxt = get_pos(x + 1);    int now = get_pos(x);    splay(nxt, 0);    splay(now, nxt);    ch[now][1] = ++tol;    newNode(ch[now][1], P, now);    push_up(now);    push_up(nxt);}void Del(int x){    int pre = get_pos(x - 1);    int nxt = get_pos(x + 1);    splay(pre, 0);    splay(nxt, pre);    ch[nxt][0] = 0;    push_up(nxt);    push_up(pre);}void Revolve(int a, int b, int T){ //[a, c - 1], [c, b]    int l = b - a + 1;    int g = (T % l + l) % l + 1;    if(g == 1) return;//原样不动!//删除[c, b]    int c = a + l - g + 1;    int pre = get_pos(c - 1);    int nxt = get_pos(b + 1);    splay(pre, 0);    splay(nxt, pre);    int p = ch[nxt][0];    ch[nxt][0] = 0;    push_up(nxt);    push_up(pre);//将[c, b]插入a的前面    pre = get_pos(a - 1);    nxt = get_pos(a);    splay(pre, 0);    splay(nxt, pre);    ch[nxt][0] = p;    fa[p] = nxt;    push_up(nxt);    push_up(pre);}int get_min(int a, int b){    int pre = get_pos(a - 1);    int nxt = get_pos(b + 1);    splay(pre, 0);    splay(nxt, pre);    return Min[ch[nxt][0]];}void init(int n){    tol = 0;    ch[0][0] = ch[0][1] = fa[0] = sz[0] = rev[0] = 0;    val[0] = sum[0] = add[0] = 0;    Min[0] = INF;    newNode(rt = n + 1, 0, 0);    newNode(ch[rt][1] = n + 2, 0, rt);    ch[ch[rt][1]][0] = build(1, n, ch[rt][1]);    tol = n + 2;}int main(){    int n, m, x, y, D, P, T;    char opt[10];    while(scanf("%d", &n) != EOF){        for(int i = 1; i <= n; i++){            scanf("%d", &a[i]);        }        init(n);        scanf("%d", &m);        while(m--){            scanf("%s", opt);            if(opt[0] == 'A'){                scanf("%d%d%d", &x, &y, &D); x++; y++;                Add(x, y, D);            }else if(opt[0] == 'R' && opt[3] == 'E'){                scanf("%d%d", &x, &y); x++; y++;                Rev(x, y);            }else if(opt[0] == 'R'){                scanf("%d%d%d", &x, &y, &T); x++; y++;                Revolve(x, y, T);            }else if(opt[0] == 'I'){                scanf("%d%d", &x, &P); x++;                Ins(x, P);            }else if(opt[0] == 'D'){                scanf("%d", &x); x++;                Del(x);            }else{                scanf("%d%d", &x, &y); x++; y++;                printf("%d\n", get_min(x, y));            }        }    }    return 0;}

原创粉丝点击