• poj3580 splay树 REVOVLE循环


    SuperMemo
    Time Limit: 5000MS   Memory Limit: 65536K
    Total Submissions: 12795   Accepted: 3989
    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
    /*
    poj3580 splay树 REVOVLE循环
    给定一个数列:a1,a2,.... an
    进行以下6种操作:
    ADD x y D : 给第x个数到第y个数加D
    REVERSE x y : 反转[x,y]
    REVOVLE x y T : 对[x,y]区间的数循环右移T次  (这个最开始没想到这么弄)
    (先把T对长度取模,然后相当于把[y-T+1,y]放到[x,y-T] 的前面,T可能出现负数或者特别大)
    INSERT x P  : 在第x个数后面插入P
    DELETE x : 删除第x个数
     MIN x y  : 查询[x,y]之间的最小的数
    
    像min,add是参照rev,size来写。然后就只有第三个操作可以一开始想不到,其它大致就是各种基本操作的组合了
    最开始写错del导致TLE几次
    
    hhh-2016-02-21 03:06:02
    */
    
    #include <functional>
    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <algorithm>
    #include <map>
    #include <cmath>
    using namespace std;
    typedef long long ll;
    typedef long  double ld;
    #define key_value ch[ch[root][1]][0]
    const int maxn = 200010;
    
    int ch[maxn][2];
    int pre[maxn],siz[maxn],num[maxn];
    int rev[maxn],key[maxn];
    int add[maxn];
    int Min[maxn],a[maxn];
    int tot;
    int root;
    void push_up(int r)
    {
        int lson = ch[r][0],rson = ch[r][1];
        siz[r] = siz[lson] + siz[rson] + 1;
        Min[r] = min(key[r],min(Min[lson],Min[rson]));
    }
    
    void update_add(int r,int val)
    {
        if(!r) return;
        key[r] += val;
        add[r] += val;
        Min[r] += val;
    }
    
    void update_rev(int r)
    {
        if(!r)return ;
        swap(ch[r][0],ch[r][1]);
        rev[r] ^= 1;
    }
    
    void push_down(int r)
    {
        if(rev[r])
        {
            update_rev(ch[r][0]);
            update_rev(ch[r][1]);
            rev[r] = 0;
        }
        if(add[r])
        {
            update_add(ch[r][0],add[r]);
            update_add(ch[r][1],add[r]);
            add[r] = 0;
        }
    }
    
    
    void NewNode(int &r,int far,int k)
    {
        r = ++tot;      //不能为0
        pre[r] = far;
        ch[r][0] = ch[r][1] = 0;
        siz[r] = 1;
        Min[r] = k;
        key[r] = k;
        rev[r] = 0;
        add[r] = 0;
    }
    
    
    void rotat(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];
        ch[x][kind] = y;
        pre[y] = x;
        push_up(y);
    }
    
    void build(int &x,int l,int r,int far)
    {
        if(l > r) return ;
        int mid = (l+r) >>1;
        NewNode(x,far,a[mid]);
        build(ch[x][0],l,mid-1,x);
        build(ch[x][1],mid+1,r,x);
        push_up(x);
    }
    
    void splay(int r,int goal)
    {
        push_down(r);
        while(pre[r] != goal)
        {
            if(pre[pre[r]] == goal)
            {
                push_down(pre[r]);
                push_down(r);
                rotat(r,ch[pre[r]][0] == r);
            }
            else
            {
                push_down(pre[pre[r]]);
                push_down(pre[r]);
                push_down(r);
                int y = pre[r];
                int kind = ch[pre[y]][0] == y;
                if(ch[y][kind] == r)
                {
                    rotat(r,!kind);
                    rotat(r,kind);
                }
                else
                {
                    rotat(y,kind);
                    rotat(r,kind);
                }
            }
        }
        push_up(r);
        if(goal == 0)
            root = r;
    }
    
    
    int get_kth(int r,int k)
    {
        push_down(r);
        int t = siz[ch[r][0]] + 1;
        if(k == t)return r;
        if(t > k) return get_kth(ch[r][0],k);
        else return get_kth(ch[r][1],k-t);
    }
    
    int get_next(int r)
    {
        push_down(r);
        if(ch[r][1] == 0)return -1;
        r = ch[r][1];
        while(ch[r][0])
        {
            r = ch[r][0];
            push_down(r);
        }
        return r;
    }
    
    void Reverse(int l,int r)
    {
        splay(get_kth(root,l),0);
        splay(get_kth(root,r+2),root);
        update_rev(key_value);
        push_up(ch[root][1]);
        push_up(root);
    }
    
    void Add(int l,int r,int val)
    {
        splay(get_kth(root,l),0);
        splay(get_kth(root,r+2),root);
        update_add(key_value,val);
        push_up(ch[root][1]);
        push_up(root);
    }
    
    void ini(int n)
    {
        tot = root = 0;
        ch[root][0] = ch[root][1] = pre[root] = siz[root] = num[root] = 0;
        Min[root] = 0x3f3f3f3f;
        rev[root] = add[root] = 0;
        NewNode(root,0,-1);
        NewNode(ch[root][1],root,-1);
        for(int i=1; i <= n; i++)
        {
            scanf("%d",&a[i]);
        }
        build(key_value,1,n,ch[root][1]);
    
        push_up(ch[root][1]);
        push_up(root);
    }
    
    int get_min(int r)
    {
        push_down(r);
        while(ch[r][0])
        {
            r = ch[r][0];
            push_down(r);
        }
        return r;
    }
    
    void Delete(int r)
    {
        splay(get_kth(root,r+1),0);
        if(ch[root][0] == 0 || ch[root][1] == 0)
        {
            root = ch[root][0] + ch[root][1];
            pre[root] = 0;
            return;
        }
        int k = get_min(ch[root][1]);
        splay(k,root);
        ch[ch[root][1]][0] = ch[root][0];
        root = ch[root][1];
        pre[ch[root][0]] = root;
        pre[root] = 0;
        push_up(root);
    }
    
    void Insert(int x,int y)
    {
        splay(get_kth(root,x+1),0);
        splay(get_kth(root,x+2),root);
        NewNode(key_value,ch[root][1],y);
        push_up(ch[root][1]);
        push_up(root);
    }
    
    int MIN(int x,int y)
    {
        splay(get_kth(root,x),0);
        splay(get_kth(root,y+2),root);
        push_up(ch[root][1]);
        push_up(root);
        return Min[key_value];
    }
    
    void Revovle(int x,int y,int T)
    {
        splay(get_kth(root,y-T+1),0);
        splay(get_kth(root,y+2),root);
        int tmp = key_value;
        //pre[key_value] = 0;
        key_value = 0;
        push_up(ch[root][1]);
        push_up(root);
    
        splay(get_kth(root,x),0);
        splay(get_kth(root,x+1),root);
        key_value = tmp;
        pre[key_value] = ch[root][1];
        push_up(ch[root][1]);
        push_up(root);
    }
    
    int main()
    {
        int n,p;
        while(scanf("%d",&n) != EOF)
        {
            ini(n);
            scanf("%d",&p);
            char opr[20];
            int x,y,z;
            while(p--)
            {
                scanf("%s",opr);
                if(strcmp(opr,"ADD") == 0)
                {
                    scanf("%d%d%d",&x,&y,&z);
                    Add(x,y,z);
                }
                else if(strcmp(opr,"INSERT") == 0)
                {
                    scanf("%d%d",&x,&y);
                    Insert(x,y);
                }
                else if(strcmp(opr,"DELETE") == 0)
                {
                    scanf("%d",&x);
                    Delete(x);
                }
                else if(strcmp(opr,"MIN") == 0)
                {
                    scanf("%d%d",&x,&y);
                    printf("%d
    ",MIN(x,y));
    //                for(int i =1;i <= 5;i++)
    //                    printf("%d
    ",Min[i]);
                }
                else if(strcmp(opr,"REVERSE") == 0)
                {
                    scanf("%d%d",&x,&y);
                    Reverse(x,y);
                }
                else if(strcmp(opr,"REVOLVE") == 0)
                {
                    scanf("%d%d%d",&x,&y,&z);
                    int t = (y-x+1);
                    z = (z%t+t)%t;
                    Revovle(x,y,z);
                }
            }
        }
        return 0;
    }
    

      

  • 相关阅读:
    php中常见的大坑,开发中应尽量避免
    ElasticSearch快速入门【建议收藏】
    OWASP Secure Headers Project
    专科是文科,是否可以报考理科的本科
    一网通办 下载发票
    “次幂”和“次方”有什么区别?
    详讲口诀“奇变偶不变,符号看象限”
    成考数学知识点 高起专
    如何下载腾讯课堂的视频
    JDK发布版本的总结
  • 原文地址:https://www.cnblogs.com/Przz/p/5409624.html
Copyright © 2020-2023  润新知