首页 > 其他 > 详细

郁闷的出纳员 题解(Splay)

时间:2019-06-13 14:40:39      阅读:126      评论:0      收藏:0      [点我收藏+]

题面

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

瞬间变水

用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\n",getnum(size[root]-val+1)+delta);
            break;
        }
    }
    cout<<ans<<endl;
    return 0;
}

 

郁闷的出纳员 题解(Splay)

原文:https://www.cnblogs.com/Rorschach-XR/p/11015682.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!