天天看点

POJ 3580 SuperMemo Splay树各种区间操作

SuperMemo

Time Limit: 5000MS Memory Limit: 65536K
Total Submissions: 11106 Accepted: 3494
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. 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:

  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 ... Ay} T 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 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

5
1 
2 
3 
4 
5
2
ADD 2 4 1
MIN 4 5      

Sample Output

5      

题意:给定一个区间,有如下几种操作,增加值,翻转,平移,在第x位置后面插入值,删除第x个值,查询区间最小值。

不难发现这些操作都是splay树的经典区间操作,照着模板来一发即可。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
#include <cmath>
#include <cstdlib>
#include <string>
#include <map>
#include <set>
#include <algorithm>
#include <functional>
#define rep(i,a,b) for (int i=a;i<((b)+1);i++)
#define Rep(i,a,b) for (int i=a;i>=b;i--)
#define foreach(e,x) for (__typeof(x.begin()) e=x.begin();e!=x.end();e++)
#define mid ((l+r)>>1)  //segement tree
#define lson (k<<1)     //segement tree
#define rson (k<<1|1)   //segement tree
#define MEM(a,x) memset(a,x,sizeof a)
#define L ch[r][0]                  //splay tree
#define R ch[r][1]                  //splay tree
#define keyvalue ch[ch[root][1]][0] //splay tree
using namespace std;
const int N=1000050;
const long long Mod=1000000007;
const int inf=0x3f3f3f3f;
typedef pair<int, int> pii;
typedef long long ll;
int pre[N],ch[N][2],key[N],root,tot,_size[N],col[N],a[N],n,q,_tot,s[N];
int rev[N],m[N];
void newnode(int &r,int fa,int k) {
    if (_tot)   r=s[_tot--];
    else r=++tot;
    pre[r]=fa;_size[r]=1;key[r]=m[r]=k;
    col[r]=rev[r]=0;
}
void update_rev(int r) {
    if (r==0)   return ;
    swap(L,R);
    rev[r]^=1;
}
void update_add(int r,int add) {
    if (r==0)   return ;
    col[r]+=add;key[r]+=add;
    m[r]+=add;
}
void push_up(int r) {
    _size[r]=_size[L]+_size[R]+1;
    m[r]=key[r];
    m[r]=min(m[r],m[L]);
    m[r]=min(m[r],m[R]);
}
void push_down(int r) {
    if (rev[r]) {
        update_rev(L);
        update_rev(R);
        rev[r]=0;
    }
    if (col[r]) {
        update_add(L,col[r]);
        update_add(R,col[r]);
        col[r]=0;
    }
}
void build(int &x,int l,int r,int fa) {
    if (l>r)    return ;
    newnode(x,fa,a[mid]);
    build(ch[x][0],l,mid-1,x);
    build(ch[x][1],mid+1,r,x);
    push_up(x);
}
void init() {
    root=tot=_tot=0;
    ch[root][0]=ch[root][1]=pre[root]=_size[root]=col[root]=rev[root]=0;
    m[root]=inf;
    newnode(root,0,inf);
    newnode(ch[root][1],root,inf);
    build(keyvalue,1,n,ch[root][1]);
    push_up(ch[root][1]);
    push_up(root);
}
void Rotate(int r,int k) {
    int y=pre[r];
    push_down(y);
    push_down(r);
    ch[y][!k]=ch[r][k];
    pre[ch[r][k]]=y;
    if (pre[y]) ch[pre[y]][ch[pre[y]][1]==y]=r;
    pre[r]=pre[y];
    ch[r][k]=y;
    pre[y]=r;
    push_up(y);
}
void Splay(int r,int g) {
    push_down(r);
    while (pre[r]!=g) {
        if (pre[pre[r]]==g) {
            push_down(pre[r]);
            push_down(r);
            Rotate(r,ch[pre[r]][0]==r);
        }else {
            push_down(pre[pre[r]]);
            push_down(pre[r]);
            push_down(r);
            int y=pre[r];
            int k=ch[pre[y]][0]==y;
            if (ch[y][k]==r) {
                Rotate(r,!k);
                Rotate(r,k);
            }else {
                Rotate(y,k);
                Rotate(r,k);
            }
        }
    }
    push_up(r);
    if (g==0)   root=r;
}
int getkth(int r,int k) {
    push_down(r);
    int t=_size[L]+1;
    if (t==k)   return r;
    if (t>k)    return getkth(L, k);
    else return getkth(R, k-t);
}
int getmin(int r) {
    push_down(r);
    while (L) {
        r=L;
        push_down(r);
    }
    return r;
}
int getmax(int r) {
    push_down(r);
    while (R) {
        r=R;
        push_down(r);
    }
    return r;
}
void Add(int l,int r,int x) {
    Splay(getkth(root, l),0);
    Splay(getkth(root, r+2),root);
    update_add(keyvalue, x);
    push_up(ch[root][1]);
    push_up(root);
}
void Reverse(int l,int r) {
    Splay(getkth(root, l),0);
    Splay(getkth(root, r+2),root);
    update_rev(keyvalue);
    push_up(ch[root][1]);
    push_up(root);
}
int query(int l,int r) {
    Splay(getkth(root, l), 0);
    Splay(getkth(root, r+2), root);
    return m[keyvalue];
}
void erase(int r) {
    if (r) {
        s[++_tot]=r;
        erase(L);erase(R);
    }
}
void Insert(int p,int x) {
    Splay(getkth(root, p+1), 0);
    Splay(getkth(root, p+2), root);
    newnode(keyvalue, ch[root][1], x);
    push_up(ch[root][1]);
    push_up(root);
}
void Delete(int x) {
    Splay(getkth(root, x), 0);
    Splay(getkth(root, x+2), root);
    erase(keyvalue);
    pre[keyvalue]=0;
    keyvalue=0;
    push_up(ch[root][1]);
    push_up(root);
}
void Revolve(int l,int r,int t) {
    int len=r-l+1;
    t=(t%len+len)%len;
    if (t==0)   return ;
    int c=r-t+1;
    Splay(getkth(root, c),0);
    Splay(getkth(root, r+2), root);
    int tmp=keyvalue;
    keyvalue=0;
    push_up(ch[root][1]);
    push_up(root);
    Splay(getkth(root, l), 0);
    Splay(getkth(root, l+1), root);
    keyvalue=tmp;
    pre[keyvalue]=ch[root][1];
    push_up(ch[root][1]);
    push_up(root);
}
char ss[20];
int main(int argc, const char * argv[]) {
    while (~scanf("%d",&n)) {
        rep(i,1,n)  scanf("%d",&a[i]);
        init();
        scanf("%d",&q);
        int x,y,z;
        rep(i,1,q) {
            scanf("%s",ss);
            if (strcmp(ss, "ADD")==0) {
                scanf("%d%d%d",&x,&y,&z);
                Add(x, y, z);
            }else if (strcmp(ss, "REVERSE")==0) {
                scanf("%d%d",&x,&y);
                Reverse(x, y);
            }else if (strcmp(ss, "REVOLVE")==0) {
                scanf("%d%d%d",&x,&y,&z);
                Revolve(x, y, z);
            }else if (strcmp(ss, "INSERT")==0) {
                scanf("%d%d",&x,&y);
                Insert(x, y);
            }else if (strcmp(ss, "DELETE")==0) {
                scanf("%d",&x);
                Delete(x);
            }else {
                scanf("%d%d",&x,&y);
                printf("%d\n",query(x, y));
            }
        }
    }
    return 0;
}
           

继续阅读