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);
            }
        }
    }
  • 相关阅读:
    分层图最短路(DP思想) BZOJ2662 [BeiJing wc2012]冻结
    动态规划 BZOJ1925 地精部落
    线性DP SPOJ Mobile Service
    线性DP codevs2185 最长公共上升子序列
    数位DP POJ3208 Apocalypse Someday
    线性DP POJ3666 Making the Grade
    杨氏矩阵 线性DP? POJ2279 Mr.Young's Picture Permutations
    tarjan强连通分量 洛谷P1262 间谍网络
    树链剖分 BZOJ3589 动态树
    二分图 BZOJ4554 [Tjoi2016&Heoi2016]游戏
  • 原文地址:https://www.cnblogs.com/Khada-Jhin/p/9688135.html
Copyright © 2011-2022 走看看