POJ 3580——SuperMemo(Splay树,经典题)

来源:互联网 发布:批量编辑图片的软件 编辑:程序博客网 时间:2024/06/13 22:34

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

—————————————————————分割线——————————————


题目大意:

对一个序列进行7种操作:

区间操作:
(1):ADD x y D                对一段区间都增加一个值value
(2):REVERSE x y         翻转一个区间
(3):REVOLVE x y T      对一个区间向右移动T步(转化成交换两个相邻的区间)
(4):INSERT x P            插入一段区间
(5):DELETE x               删除一段区间
(6):MIN x y                     返回一段区间的最小值

思路:

对于右移操作就是讲一段区间分割成两半,然后再合并

[x,a][a+1,y],先将a-1旋转到根,再将a+1旋转到根的右儿子,然后把右儿子的左子树割下来,再将y旋转到根,y+1旋转到根的右儿子,最后将被割下来的子树链接到y+1


注意点:

maxn定义成100001会TL!!!

#include<iostream>#include<cstring>#include<cstdio>#include<algorithm>#define Key_value ch[ch[root][1]][0]#define REP(i,n) for(int i=0;i<(n);++i)const int INF=1<<30;const int maxn=100010;using namespace std;int root,tot1,ch[maxn][2],key[maxn],Min[maxn],pre[maxn];int s[maxn],tot2;int rev[maxn],add[maxn],size[maxn];int a[maxn];int n,q;void update_rev(int rt){    if(!rt) return ;    swap(ch[rt][0],ch[rt][1]);    rev[rt]^=1;}void update_add(int rt,int d){    if(!rt) return ;    key[rt]+=d;    add[rt]+=d;    Min[rt]+=d;}void push_up(int rt){    int lson=ch[rt][0],rson=ch[rt][1];    size[rt]=size[lson]+size[rson]+1;    Min[rt]=min(key[rt],min(Min[lson],Min[rson]));}void push_down(int rt){    int lson=ch[rt][0],rson=ch[rt][1];    if(add[rt]) {        update_add(lson,add[rt]);        update_add(rson,add[rt]);        add[rt]=0;    }    if(rev[rt]) {        update_rev(lson);        update_rev(rson);        rev[rt]=0;    }}void NewNode(int &rt,int f,int k){    if(tot2) rt=s[tot2--];    else rt=++tot1;    ch[rt][0]=ch[rt][1]=0;    pre[rt]=f;    key[rt]=k;    size[rt]=1;    add[rt]=rev[rt]=0;    Min[rt]=k;}void build(int &rt,int l,int r,int f){    if(l>r) return ;    int mid=(l+r)>>1;    NewNode(rt,f,a[mid]);    build(ch[rt][0],l,mid-1,rt);    build(ch[rt][1],mid+1,r,rt);    push_up(rt);}void Init(){    root=tot1=tot2=0;    rev[root]=add[root]=ch[root][0]=ch[root][1]=pre[root]=size[root]=0;    Min[root]=INF;    NewNode(root,0,-1);    NewNode(ch[root][1],root,-1);    REP(i,n) scanf("%d",&a[i]);    build(Key_value,0,n-1,ch[root][1]);    push_up(ch[root][1]);    push_up(root);}void Rotate(int x,int kind){    int y=pre[x];    push_down(y);    push_down(x);    ch[y][!kind]=ch[x][kind];    pre[ch[x][kind]]=y;    if(pre[y])        ch[pre[y]][ch[pre[y]][1]==y]=x;    pre[x]=pre[y];    pre[y]=x;    ch[x][kind]=y;    push_up(y);}void Splay(int x,int goal){    push_down(x);    while(pre[x]!=goal) {        if(pre[pre[x]]==goal) {            Rotate(x,ch[pre[x]][0]==x);        } else {            int y=pre[x];            int kind=ch[pre[y]][0]==y;            if(ch[y][kind]==x) {                Rotate(x,!kind);                Rotate(x,kind);            } else {                Rotate(y,kind);                Rotate(x,kind);            }        }    }    push_up(x);    if(goal==0) root=x;}int Get_kth(int rt,int k){    push_down(rt);    int z=size[ch[rt][0]]+1;    if(z==k) return rt;    if(z>k) return Get_kth(ch[rt][0],k);    else return Get_kth(ch[rt][1],k-z);}void Add(int x,int y,int d){    Splay(Get_kth(root,x),0);    Splay(Get_kth(root,y+2),root);    update_add(Key_value,d);    push_up(ch[root][1]);    push_up(root);}void Reverse(int x,int y){    Splay(Get_kth(root,x),0);    Splay(Get_kth(root,y+2),root);    update_rev(Key_value);}void Revolve(int x,int y,int k){    if(!k) return ;    int l=y-x+1;    l=y-(k%l+l)%l;    Splay(Get_kth(root,x),0);    Splay(Get_kth(root,l+2),root);    int tmp=Key_value;    Key_value=0;//    pre[Key_value]=0;    push_up(ch[root][1]);    push_up(root);    Splay(Get_kth(root,y-l+x),0);    Splay(Get_kth(root,y-l+x+1),root);    Key_value=tmp;    pre[Key_value]=ch[root][1];    push_up(ch[root][1]);    push_up(root);}void Insert(int x,int v){    Splay(Get_kth(root,x+1),0);    Splay(Get_kth(root,x+2),root);    NewNode(Key_value,ch[root][1],v);    push_up(ch[root][1]);    push_up(root);}void erase(int rt){    if(!rt) return ;    s[++tot2]=rt;    erase(ch[rt][0]);    erase(ch[rt][1]);}void Delete(int x){    Splay(Get_kth(root,x),0);    Splay(Get_kth(root,x+2),root);    erase(Key_value);    pre[Key_value]=0;    Key_value=0;    push_up(ch[root][1]);    push_up(root);}int Get_answer(int x,int y){    Splay(Get_kth(root,x),0);    Splay(Get_kth(root,y+2),root);    return Min[Key_value];}int main(){    while(scanf("%d",&n)!=EOF){        Init();scanf("%d",&q);char str[10];int l,r,k;while(q--){scanf("%s",str);if(!strcmp(str,"ADD")){scanf("%d%d%d",&l,&r,&k);Add(l,r,k);}else if(!strcmp(str,"REVERSE")){scanf("%d%d",&l,&r);Reverse(l,r);}else if(!strcmp(str,"REVOLVE")){scanf("%d%d%d",&l,&r,&k);Revolve(l,r,k);}else if(!strcmp(str,"INSERT")){scanf("%d%d",&l,&k);Insert(l,k);}else if(!strcmp(str,"DELETE")){scanf("%d",&l);Delete(l);}else{scanf("%d%d",&l,&r);printf("%d\n",Get_answer(l,r));}}}return 0;}



0 0
原创粉丝点击