zoukankan      html  css  js  c++  java
  • 洛谷P1486 [NOI2004]郁闷的出纳员 平衡树Splay

    P1486 [NOI2004]郁闷的出纳员

    题目链接

    题意

    第一行有两个整数 (n)(min)(n) 表示下面有多少条命令,(min) 表示工资下界。

    接下来的 (n) 行,每行一个字符 (x) 和一个整数 (k),表示一条命令。命令可以是以下四种之一:

    • I k 新建一个工资档案,初始工资为 (k)。如果某员工的初始工资低于工资下界,他将立刻离开公司。
    • A k 把每位员工的工资加上 (k)
    • S k 把每位员工的工资扣除 (k)
    • F k 查询第 (k) 多的工资。

    在初始时,可以认为公司里一个员工也没有。

    分析

    (delta)表示所有员工的修改量,每个员工实际的工资为(k+delta)

    对于新加进来的员工,为了消除历史修改的影响,插入(k-delta)

    对于增加工资操作,直接(delta+=k)

    对于扣除工资操作,先(delta-=k),然后我们要找到所有(k+delta<min)的员工,移项一下即为(k<min-delta),可以先插入一个权值(min-delta),将其旋转到根节点,左子树即为所有要删除的员工,直接将左子树删除即可,然后将(min-delta)删除。

    查询第(k)多就是模板操作了。

    Code

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<iomanip>
    #include<sstream>
    #include<cstdio>
    #include<string>
    #include<vector>
    #include<bitset>
    #include<queue>
    #include<cmath>
    #include<stack>
    #include<set>
    #include<map>
    #define rep(i,x,n) for(int i=x;i<=n;i++)
    #define per(i,n,x) for(int i=n;i>=x;i--)
    #define sz(a) int(a.size())
    #define rson mid+1,r,p<<1|1
    #define pii pair<int,int>
    #define lson l,mid,p<<1
    #define ll long long
    #define pb push_back
    #define mp make_pair
    #define se second
    #define fi first
    using namespace std;
    const double eps=1e-8;
    const int mod=1e9+7;
    const int N=3e5+10;
    const int inf=1e9;
    int n,m;
    int rt,tot,ch[N][2],sz[N],fa[N],cnt[N];
    ll val[N],d;
    struct Splay{
        void maintain(int x){
            sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+cnt[x];
        }
        bool get(int x){
            return x==ch[fa[x]][1];
        }
        void clear(int x){
            ch[x][0]=ch[x][1]=fa[x]=val[x]=sz[x]=cnt[x]=0;
        }
        void rotate(int x){
            int y=fa[x],z=fa[y],chk=get(x);
            ch[y][chk]=ch[x][chk^1];
            fa[ch[x][chk^1]]=y;
            ch[x][chk^1]=y;
            fa[y]=x;
            fa[x]=z;
            if(z) ch[z][ y==ch[z][1] ]=x;
            maintain(y);
            maintain(x);
        }
        void splay(int x,int goal=0){
            for(int f;(f=fa[x])!=goal;rotate(x)){
                if(fa[f]!=goal) rotate(get(x)==get(f)?f:x); 
            }
            if(goal==0) rt=x;
        }
        void ins(ll k){
            if(!rt){
                val[++tot]=k;
                cnt[tot]++;
                rt=tot;
                maintain(rt);
                return;
            }
            int cnr=rt,f=0;
            while(1){
                if(val[cnr]==k){
                    cnt[cnr]++;
                    maintain(cnr);
                    maintain(f);
                    splay(cnr);
                    break;
                }
                f=cnr;
                cnr=ch[cnr][val[cnr]<k];
                if(!cnr){
                    val[++tot]=k;
                    cnt[tot]++;
                    fa[tot]=f;
                    ch[f][val[f]<k]=tot;
                    maintain(tot);
                    maintain(f);
                    splay(tot);
                    break;
                }
            }
        }
        int rk(ll k){
            int res=0,cnr=rt;
            while(1){
                if(k<val[cnr]){
                    cnr=ch[cnr][0];
                }else{
                    res+=sz[ch[cnr][0]];
                    if(k==val[cnr]){
                        splay(cnr);
                        return res+1;
                    }
                    res+=cnt[cnr];
                    cnr=ch[cnr][1];
                }
            }
        }
        ll kth(int k){
            int cnr=rt;
            while(1){
                if(ch[cnr][1]&&sz[ch[cnr][1]]>=k){
                    cnr=ch[cnr][1];
                }else{
                    k-=cnt[cnr]+sz[ch[cnr][1]];
                    if(k<=0){
                        return val[cnr];
                    }
                    cnr=ch[cnr][0];
                }
            }
        }
        int pre(){
            int cnr=ch[rt][0];
            while(ch[cnr][1]) cnr=ch[cnr][1];
            splay(cnr);
            return cnr;
        }
        void del(int k){
            rk(k);
            if(cnt[rt]>1){
                cnt[rt]--;
                maintain(rt);
                return;
            }
            if(!ch[rt][0]&&!ch[rt][1]){
                clear(rt);
                rt=0;
                return;
            }
            if(!ch[rt][0]){
                int cnr=rt;
                rt=ch[rt][1];
                fa[rt]=0;
                clear(cnr);
                return;
            }
            if(!ch[rt][1]){
                int cnr=rt;
                rt=ch[rt][0];
                fa[rt]=0;
                clear(cnr);
                return;
            }
            int cnr=rt,x=pre();
            splay(x);
            fa[ch[cnr][1]]=x;
            ch[x][1]=ch[cnr][1];
            clear(cnr);
            maintain(rt);
        }
    }S;
    int main(){
        //ios::sync_with_stdio(false);
        //freopen("in","r",stdin);
        scanf("%d%d",&n,&m);
        int cnt=0;
        rep(i,1,n){
            char c[2];
            int k;
            scanf("%s%d",c,&k);
            if(c[0]=='I'){
                if(k>=m){
                    S.ins(k-d);
                    cnt++;
                }
            }else if(c[0]=='A'){
                d+=k;
            }else if(c[0]=='S'){
                d-=k;
                S.ins(m-d);
                int pos=ch[rt][0];
                S.clear(pos);
                ch[rt][0]=0;
                S.maintain(rt);
                S.del(m-d);
            }else{
                if(sz[rt]<k) puts("-1");
                else printf("%lld
    ",S.kth(k)+d);
            }
        }
        printf("%d
    ",cnt-sz[rt]);
        return 0;
    }
    
  • 相关阅读:
    vs2008下directx11环境配置 k
    sps2003通知实现技巧
    我勒个去,键盘按键坏了怎么办解决按键替换问题
    多重循环的退出问题 ifbreak
    【转】 星号的秘密
    ??运算符,你是干嘛用的
    【转】C++中的const
    性能测试基础知识
    Andriod Studio 运行kotlin main方法异常 Manifest merger failed with multiple errors
    Android 文本后面添加标签
  • 原文地址:https://www.cnblogs.com/xyq0220/p/13512281.html
Copyright © 2011-2022 走看看