zoukankan      html  css  js  c++  java
  • 郁闷的出纳员 题解(Splay)

    题面

    看似是要区间修改,然而实际上只需要维护底线和工资的相对大小关系,

    瞬间变水

    用delta记录对工资的加减,那么添加节点时点权应-delta,输出时+delta

    几种操作中减少工资较麻烦:

    1.delta-=val;

    2.删点

    求前驱转到根,删除左子树

    这里的删除不用一个一个暴力删,直接断掉子树关系即可

    至于求k大 我比较懒直接改成求size-k+1小 (逃)

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    using namespace std;
    const int N=1e5+5;
    int n,fa[N],cnt[N],son[N][3],size[N],key[N],type,root;
    int line,ans,num,delta;
    void clear(int x)
    {
        fa[x]=cnt[x]=son[x][1]=son[x][0]=size[x]=key[x]=0;
    }
    bool judge(int x)
    {
        return son[fa[x]][1]==x;
    }
    void up(int x)
    {
        if(x)
        {
            size[x]=cnt[x];
            if(son[x][0])size[x]+=size[son[x][0]];
            if(son[x][1])size[x]+=size[son[x][1]];
        }
    }
    void rotate(int x)
    {
        int old=fa[x],oldf=fa[old],lr=judge(x);
        son[old][lr]=son[x][lr^1];
        fa[son[old][lr]]=old;
        son[x][lr^1]=old;
        fa[old]=x;
        fa[x]=oldf;
        if(oldf)son[oldf][son[oldf][1]==old]=x;
        up(old);up(x);
    }
    void splay(int x)
    {
        for(int f;f=fa[x];rotate(x))
            if(fa[f])rotate(judge(x)==judge(f)?f:x);
        root=x;
    }
    void ins(int x)
    {
        if(!root)
        {
            type++;
            key[type]=x;
            root=type;
            cnt[type]=size[type]=1;
            fa[type]=son[type][0]=son[type][1]=0;
            return ;
        }
        int now=root,f=0;
        while(1)
        {
            if(x==key[now])
            {
                cnt[now]++;
                up(now);
                up(f);
                splay(now);
                return ;
            }
            f=now;now=son[now][key[now]<x];
            if(!now)
            {
                type++;
                size[type]=cnt[type]=1;
                son[type][0]=son[type][1]=0;
                son[f][x>key[f]]=type;
                fa[type]=f;
                key[type]=x;
                up(f);splay(type);
                return ;
            }
        }
    }
    int getnum(int x)
    {
        int now=root;
        while(1)
        {
            if(son[now][0]&&x<=size[son[now][0]])now=son[now][0];
            else
            {
                int tmp=size[son[now][0]]+cnt[now];
                if(x<=tmp)
                    return key[now];
                x-=tmp;now=son[now][1];
            }
        }
    }
    int pre()
    {
        if(cnt[root]>1)return root;
        int now=son[root][0];
        while(son[now][1])now=son[now][1];
        return now;
    }
    void del(int x)
    {
        //changeroot(x);
        if(cnt[root]>1)
        {
            cnt[root]--;
            up(root);
            return ;
        }
        if(!son[root][0]&&!son[root][1])
        {
            clear(root);
            root=0;
            return ;
        }
        if(!son[root][0])
        {
            int old=root;
            root=son[root][1];
            fa[root]=0;
            clear(old);
            return ;
        }
        else if(!son[root][1])
        {
            int old=root;
            root=son[root][0];
            fa[root]=0;
            clear(old);
            return ;
        }
        int old=root,L=pre();
        splay(L);
        son[root][1]=son[old][1];
        fa[son[old][1]]=root;
        clear(old);
        up(root);
    }
    void del_tree()
    {
        fa[son[root][0]]=0;
        size[root]-=size[son[root][0]];
        son[root][0]=0;
    }
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9')
        {if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9')
        {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
        return x*f;
    }
    int main()
    {
        n=read();line=read();
        char op[3];int val; 
        for(int i=1;i<=n;i++)
        {
            scanf("%s",op);val=read();
            switch(op[0])
            {
                case 'I':
                if(val<line)break;
                else
                {
                    ins(val-delta);
                    break;
                }
                case 'A':
                delta+=val;break;
                case 'S':
                delta-=val;
                ins(line-delta);
                ans+=son[root][0]?size[son[root][0]]:0;
                del_tree();
                del(val-delta);
                break;
                case 'F':
                if(size[root]<val)puts("-1");
                else printf("%d
    ",getnum(size[root]-val+1)+delta);
                break;
            }
        }
        cout<<ans<<endl;
        return 0;
    }
  • 相关阅读:
    23种设计模式中的模板模式
    23种设计模式中的外观模式
    div,li,span自适应宽度换行问题
    监听自定义ItemRender的事件
    flex acionscript png图片去除多余空白,生成合适大小图片
    项目中用到RouteTable,发布到IIS7中无法访问
    记录Castle ActiveRecord访问Sqlite的配置
    如何卸载软件
    linux 下route命令
    linux 下 ifcfg-eth0 配置 以及ifconfig、ifup、ifdown区别
  • 原文地址:https://www.cnblogs.com/Rorschach-XR/p/11015682.html
Copyright © 2011-2022 走看看