zoukankan      html  css  js  c++  java
  • BZOJ1895Pku3580 supermemo——非旋转treap

    题目描述

    给出一个初始序列fA1;A2;:::Ang,要求你编写程序支持如下操作: 1. ADDxyD:给子序列fAx:::Ayg的每个元素都加上D。例如对f1,2, 3,4,5g执行"ADD 241" 会得到f1,3,4,5,5g。 2. REVERSExy:将子序列fAx:::Ayg翻转。例如对f1,2,3,4,5g执 行"REVERSE 24"会得到f1,4,3,2,5g。 3. REVOLVExyT:将子序列fAx:::Ayg旋转T个单位。例如, 对f1,2,3,4,5g执行"REVOLVE 242"会得到f1,3,4,2,5g。 4. INSERTxP:在Ax后插入P。例如,对f1,2,3,4,5g执行"INSERT 24"会得到f1,2,4,3,4,5g。 5. DELETEx:删去Ax。例如,对f1,2,3,4,5g执行"DELETE 2"会得 到f1,3,4,5g。 6. MINxy:查询子序列fAx:::Ayg中的最小元素。例如,对于序列f1, 2,3,4,5g,询问"MIN 24"的返回应为2。

    输入

    第一行包含一个整数n,表示初始序列的长度。 以下n行每行包含一个整数,描述初始的序列。 接下来一行包含一个整数m,表示操作的数目。 以下m行每行描述一个操作。

    输出

    对于所有"MIN"操作,输出正确的答案,每行一个。

    样例输入

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

    样例输出

    5

    提示

    输入、输出以及中间运算结果均不会超过32位整数。
    对于30%的数据,n;m 6 1000;
    对于100%的数据,n;m 6 100000。

     
    序列终结者加强版,注意旋转操作的T可能大于区间长因此要取模,其他操作比较常规,插入删除直接断裂开之后在中间删掉或者加入;区间操作将treap断裂成三段,对中间一段打标记即可,标记在遍历点时下传。
    #include<set>
    #include<map>
    #include<stack>
    #include<queue>
    #include<cmath>
    #include<cstdio>
    #include<vector>
    #include<bitset>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define ll long long
    using namespace std;
    int cnt;
    int n,m;
    int root;
    int L,R,C;
    int w,x,y,z;
    char ch[16];
    int a[300010];
    int s[300010];
    int r[300010];
    int v[300010];
    int mn[300010];
    int ls[300010];
    int rs[300010];
    int size[300010];
    int build(int val)
    {
        int rt=++cnt;
        v[rt]=val;
        size[rt]=1;
        r[rt]=rand();
        mn[rt]=val;
        return rt;
    }
    void rotate(int rt)
    {
        swap(ls[rt],rs[rt]);
        s[rt]^=1;
    }
    void add(int rt,int val)
    {
        a[rt]+=val;
        mn[rt]+=val;
        v[rt]+=val;
    }
    void pushup(int rt)
    {
        size[rt]=size[ls[rt]]+size[rs[rt]]+1;
        mn[rt]=v[rt];
        if(ls[rt])
        {
            mn[rt]=min(mn[rt],mn[ls[rt]]);
        }
        if(rs[rt])
        {
            mn[rt]=min(mn[rt],mn[rs[rt]]);
        }
    }
    void pushdown(int rt)
    {
        if(s[rt])
        {
            if(ls[rt])
            {
                rotate(ls[rt]);
            }
            if(rs[rt])
            {
                rotate(rs[rt]);
            }
            s[rt]^=1;
        }
        if(a[rt])
        {
            if(ls[rt])
            {
                add(ls[rt],a[rt]);
            }
            if(rs[rt])
            {
                add(rs[rt],a[rt]);
            }
            a[rt]=0;
        }
    }
    int merge(int x,int y)
    {
        if(!x||!y)
        {
            return x+y;
        }
        pushdown(x);
        pushdown(y);
        if(r[x]<r[y])
        {
            rs[x]=merge(rs[x],y);
            pushup(x);
            return x;
        }
        else
        {
            ls[y]=merge(x,ls[y]);
            pushup(y);
            return y;
        }
    }
    void split(int rt,int k,int &x,int &y)
    {
        if(!rt)
        {
            x=y=0;
            return ;
        }
        pushdown(rt);
        if(size[ls[rt]]<k)
        {
            x=rt;
            split(rs[rt],k-size[ls[rt]]-1,rs[x],y);
        }
        else
        {
            y=rt;
            split(ls[rt],k,x,ls[y]);
        }
        pushup(rt);
    }
    int main()
    {
        srand(20020419);
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&x);
            root=merge(root,build(x));
        }
        scanf("%d",&m);
        while(m--)
        {
            scanf("%s",ch);
            if(ch[0]=='A')
            {
                scanf("%d%d%d",&L,&R,&C);
                split(root,L-1,x,y);
                split(y,R-L+1,y,z);
                add(y,C);
                root=merge(merge(x,y),z);
            }
            else if(ch[0]=='R'&&ch[3]=='E')
            {
                scanf("%d%d",&L,&R);
                split(root,L-1,x,y);
                split(y,R-L+1,y,z);
                rotate(y);
                root=merge(merge(x,y),z);
            }
            else if(ch[0]=='R'&&ch[3]=='O')
            {
                scanf("%d%d%d",&L,&R,&C);
                C%=(R-L+1);
                if(C==0)
                {
                    continue;
                }
                C=(R-L+1)-C;
                split(root,L-1,x,y);
                split(y,R-L+1,y,z);
                split(y,C,y,w);
                root=merge(merge(x,merge(w,y)),z);
            }
            else if(ch[0]=='I')
            {
                scanf("%d%d",&L,&C);
                split(root,L,x,y);
                root=merge(merge(x,build(C)),y);
            }
            else if(ch[0]=='D')
            {
                scanf("%d%d",&L,&C);
                split(root,L-1,x,y);
                split(y,1,y,z);
                root=merge(x,z);
            }
            else
            {
                scanf("%d%d",&L,&R);
                split(root,L-1,x,y);
                split(y,R-L+1,y,z);
                printf("%d
    ",mn[y]);
                root=merge(merge(x,y),z);
            }
        }
    }
  • 相关阅读:
    Google字典API与语音库
    CentOS 6.0 安装字符界面/text 安装/文本安装
    W3C Strict 验证的几个注意事项
    前端开发必备的6个Firefox插件
    自制的一套Aptana配色方案
    Firebug Console 与命令行全集
    项目管理的“三边六拍”!
    不使用第三个变量,交换两变量的值 (总结篇)
    dba学习笔记
    三思涂抹oracle(笔记)
  • 原文地址:https://www.cnblogs.com/Khada-Jhin/p/9688135.html
Copyright © 2011-2022 走看看