zoukankan      html  css  js  c++  java
  • BZOJ 1503 郁闷的出纳员(splay)

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1503

    题意:给出一个数列(初始为空),给出一个最小值Min,当数列中的数字小于Min时自动删除。四种操作:(1)数列中增加一个元素,设置初始值x;若x小于Min则不插入;(2)所有的元素增加一个值det;(3)所有的元素减小一个值det;此时有可能有一些会被删除(4)询问目前所有元素中第K大的。最后输出删除了多少个。

    思路:首先,因为增加和减小是对所有元素而言,因此这个值我们不插入而是单独保存,设这个值为det。那么插入一个元素x,我们插入x-det,这样保持插入的所有元素的真实值都是其加上det。然后,每次减小时,我们需要进行删除,那么插入一个Min-det的节点,并将其调整到根节点,然后左子树就是被删除的。之后,将根节点的右节点变为根节点。



    int tot,root,k[N],L[N],R[N],f[N],s[N];


    inline void pushUp(int x)
    {
        if(x) s[x]=s[L[x]]+s[R[x]]+1;
    }


    inline void zig(int x)
    {
        int y=f[x],z=f[y];
        if(z) L[z]==y?L[z]=x:R[z]=x;
        f[x]=z;
        L[y]=R[x];
        if(R[x]) f[R[x]]=y;
        R[x]=y;
        f[y]=x;
        pushUp(y);
        pushUp(x);
    }




    inline void zag(int x)
    {
        int y=f[x],z=f[y];
        if(z) L[z]==y?L[z]=x:R[z]=x;
        f[x]=z;
        R[y]=L[x];
        if(L[x]) f[L[x]]=y;
        L[x]=y;
        f[y]=x;
        pushUp(y);
        pushUp(x);
    }




    inline void splay(int x)
    {
        int y;
        while(y=f[x])
        {
            if(f[y])
            {
                if(L[f[y]]==y) L[y]==x?(zig(y),zig(x)):(zag(x),zig(x));
                else R[y]==x?(zag(y),zag(x)):(zig(x),zag(x));
            }
            else L[y]==x?zig(x):zag(x);
        }
        root=x;
    }




    inline void insert(int key)
    {
        int x=root,y=0;
        for(;x;y=x,x=key<=k[x]?L[x]:R[x]);
        k[x=++tot]=key;
        if(y) key<=k[y]?L[y]=x:R[y]=x;
        f[x]=y; s[x]=1; splay(x);
    }






    inline int select(int K)
    {
        int x=root;
        for(;s[L[x]]+1!=K;K<=s[L[x]]?x=L[x]:(K-=s[L[x]]+1,x=R[x]));
        splay(x);
        return k[x];
    }


    int main()
    {
        int n,m,d=0,ans=0;
        RD(n,m);
        while(n--)
        {
            char op[10];
            int x;
            scanf("%s%d",op,&x);
            if(op[0]=='I'&&x>= m) insert(x-d);
            else if(op[0]=='A') d+=x;
            else if(op[0]=='S')
            {
                insert(m-(d-=x));
                ans+=s[L[root]]; root=R[root]; f[root]=0;
                pushUp(root);
            }
            else if(op[0]=='F') PR(x>s[root]?-1:select(s[root]-x+1)+d);
        }
        PR(ans);
        return 0;
    }





  • 相关阅读:
    计算机作业(四)
    计算作业(三)衡阳汽车工程学院
    数制转换
    第十一次作业——PPT内容
    第三次作业——计算机用CMD命令关机建立文件夹
    第一次作业——PC端配置详细2017级机械设计新生杨路生
    PC端配置详细 2017级机械设计新生 刘林峰
    数制转换
    计算机基础作业 17级-车辆工程-周金霖
    计算机应用基础教程作业 车辆工程 冯大昕
  • 原文地址:https://www.cnblogs.com/jianglangcaijin/p/3458169.html
Copyright © 2011-2022 走看看