zoukankan      html  css  js  c++  java
  • poj3580 SuperMemo (Splay+区间内向一个方向移动)

    Time Limit: 5000MS   Memory Limit: 65536K
    Total Submissions: 13550   Accepted: 4248
    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, {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

    题意:给你n个数组成的一个序列,让你写一个数据结构支持下列操作:1.区间[x,y]增加c 2.区间[x,y]翻转 3.区间[x,y]向右移动c次,如1 2 3 4 5向右移动2次就变成4 5 1 2 3。4.在第x个数后插入c 5.删除第x个数 6.求出区间[x,y]内的最小值。


    思路:要维护rev[],mx[],add[]分别表示旋转标记,最小值以及成段增加的标记,然后这题和其他题不用的地方在于多了一个区间内移动的操作,我们要先求出c被y-x+1除后的余数,如果为0就不变,如果不为0,那么画图可以看出这个操作等价于把[y-c+1,y]移到[x,y-c]这个区间的前面,然后就可以直接做了。


    #include<iostream>
    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include<math.h>
    #include<vector>
    #include<map>
    #include<set>
    #include<string>
    #include<bitset>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    typedef long double ldb;
    #define inf 99999999
    #define pi acos(-1.0)
    #define Key_value ch[ch[rt][1]][0]
    #define maxn 1000010
    int n;
    int cnt,rt;
    int pre[maxn],ch[maxn][2],sz[maxn],rev[maxn],zhi[maxn],mx[maxn],add[maxn];
    int b[maxn],tot2;//内存池和容量
    int a[maxn];
    
    void update_rev(int x)
    {
        if(!x)return;       //!!!
        rev[x]^=1;
        swap(ch[x][0],ch[x][1]);
    }
    void update_add(int x,int value)
    {
        zhi[x]+=value;
        add[x]+=value;
        mx[x]+=value;
    }
    
    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 pushup(int x)
    {
        int t=zhi[x];
        if(ch[x][0])t=min(t,mx[ch[x][0] ]);
        if(ch[x][1])t=min(t,mx[ch[x][1] ]);
        mx[x]=t;
        sz[x]=sz[ch[x][0] ]+sz[ch[x][1] ]+1;
    }
    
    void Treavel(int x)
    {
        if(x)
        {
            pushdown(x);
            Treavel(ch[x][0]);
            printf("结点:%2d: 左儿子 %2d 右儿子 %2d 父结点 %2d size = %2d zhi = %2d minx=%2d add=%2d
    ",x,ch[x][0],ch[x][1],pre[x],sz[x],zhi[x],mx[x],add[x]);
            Treavel(ch[x][1]);
        }
    }
    void debug()
    {
        printf("root:%d
    ",rt);
        Treavel(rt);
    }
    
    void newnode(int &x,int father,int value)
    {
        if(tot2)x=b[tot2--];
        else x=++cnt;
        pre[x]=father;ch[x][0]=ch[x][1]=0;sz[x]=1;rev[x]=0;zhi[x]=value;mx[x]=value;add[x]=0;
    }
    
    void build(int &x,int l,int r,int father)
    {
        if(l>r)return;
        int mid=(l+r)/2;
        newnode(x,father,a[mid]);
        build(ch[x][0],l,mid-1,x);
        build(ch[x][1],mid+1,r,x);
        pushup(x);
    }
    
    void init()
    {
        cnt=rt=tot2=0;
        pre[0]=ch[0][0]=ch[0][1]=sz[0]=rev[0]=zhi[0]=mx[0]=add[0]=0;
    
    
        newnode(rt,0,-1);
        newnode(ch[rt][1],rt,-1);
        build(Key_value,1,n,ch[rt][1]);
        pushup(ch[rt][1]);
        pushup(rt);
    }
    
    void rotate(int x,int p)
    {
        int y=pre[x];
        pushdown(y);pushdown(x);
        ch[y][!p]=ch[x][p];
        pre[ch[x][p] ]=y;
        if(pre[y])ch[pre[y] ][ch[pre[y] ][1]==y ]=x;
        pre[x]=pre[y];
        ch[x][p]=y;
        pre[y]=x;
        pushup(y);pushup(x);
    }
    void splay(int x,int goal)
    {
        pushdown(x);
        while(pre[x]!=goal){
            if(pre[pre[x] ]==goal){
                pushdown(pre[x]);pushdown(x);
                rotate(x,ch[pre[x]][0]==x);
            }
            else{
                int y=pre[x];int z=pre[y];
                pushdown(z);pushdown(y);pushdown(x);
                int p=ch[pre[y] ][0]==y;
                if(ch[y][p]==x )rotate(x,!p);
                else rotate(y,p);
                rotate(x,p);
            }
        }
        if(goal==0)rt=x;
        pushup(x);
    }
    
    int get_kth(int x,int k)
    {
        int i,j;
        pushdown(x);
        int t=sz[ch[x][0] ]+1;
        if(t==k)return x;
        if(t<k)return get_kth(ch[x][1],k-t);
        return get_kth(ch[x][0],k);
    }
    
    void erase(int x)
    {
        if(x==0)return; //!!!
        b[++tot2]=x;
        erase(ch[x][0]);
        erase(ch[x][1]);
    }
    
    void Add(int x,int y,int c)
    {
        splay(get_kth(rt,x),0);
        splay(get_kth(rt,y+2),rt);
        update_add(Key_value,c);
        pushup(ch[rt][1]);
        pushup(rt);
    }
    
    
    void Reverse(int x,int y)
    {
        splay(get_kth(rt,x),0);
        splay(get_kth(rt,y+2),rt);
        update_rev(Key_value);
        pushup(ch[rt][1]);
        pushup(rt);
    }
    void Insert(int x,int value)
    {
        int i,j;
        splay(get_kth(rt,x+1),0);
        splay(get_kth(rt,x+2),rt);
        newnode(Key_value,ch[rt][1],value);
        pushup(ch[rt][1]);
        pushup(rt);
    }
    
    void Rotate(int x,int y,int c)
    {
        int len=y-x+1;
        c=(c%len+len)%len;
        if(c==0)return;
        splay(get_kth(rt,y-c+1),0);
        splay(get_kth(rt,y+2 ),rt);
        int tmp=Key_value;
        Key_value=0;
        pushup(ch[rt][1]);
        pushup(rt);
    
        splay(get_kth(rt,x),0 );
        splay(get_kth(rt,x+1),rt);
        Key_value=tmp;
        pre[tmp]=ch[rt][1];
        pushup(ch[rt][1]);
        pushup(rt);
    }
    
    
    void Delete(int pos,int tot)
    {
        splay(get_kth(rt,pos),0);
        splay(get_kth(rt,pos+tot+1),rt);
        erase(Key_value);
        Key_value=0;
        pushup(ch[rt][1]);
        pushup(rt);
    }
    
    int Get_min(int x,int y)
    {
        splay(get_kth(rt,x),0);
        splay(get_kth(rt,y+2),rt);
        return mx[Key_value];
    }
    
    int main()
    {
        int m,i,j,pos,tot,c,d,e,f;
        char s[10];
        while(scanf("%d",&n)!=EOF)
        {
            for(i=1;i<=n;i++){
                scanf("%d",&a[i]);
            }
            scanf("%d",&m);
            init();
            //debug();
            for(i=1;i<=m;i++){
                scanf("%s",s);
                if(s[0]=='A'){
                    scanf("%d%d%d",&c,&d,&e);
                    Add(c,d,e);
                }
                if(s[0]=='R' && s[3]=='E'){
                    scanf("%d%d",&c,&d);
                    Reverse(c,d);
                }
                if(s[0]=='R' && s[3]=='O'){
                    scanf("%d%d%d",&c,&d,&e);
                    Rotate(c,d,e);
                }
                if(s[0]=='I'){
                    scanf("%d%d",&c,&d);
                    Insert(c,d);
                }
                if(s[0]=='D'){
                    scanf("%d",&c);
                    Delete(c,1);
                }
                if(s[0]=='M'){
                    scanf("%d%d",&c,&d);
                    printf("%d
    ",Get_min(c,d));
                    //printf("1
    ");
                }
                //debug();
            }
        }
        return 0;
    }
    


  • 相关阅读:
    java的类继承(与c++对比)
    java的数据类型、自动拆装箱、字面量
    java中关键字static和final
    JVM之JIT
    java之JIT(Just in time)
    栈和堆
    C++中vector的使用
    canvas
    ajax笔记
    CSS笔记
  • 原文地址:https://www.cnblogs.com/herumw/p/9464481.html
Copyright © 2011-2022 走看看