zoukankan      html  css  js  c++  java
  • P1486 [NOI2004]郁闷的出纳员

    我是题面

    题意应该比较清晰,很明显,平衡树轻松应对,我用的是Splay

    对于新建操作,我们可以记录之前对工资的调整(sum),在平衡树中插入(k-sum)即可,别忘了判断(k)是否大于等于(min)

    对于增加操作,我们给(sum)加上(k)即可

    对于减小操作,我们给(sum)减去(k),然后需要判断一下是否有人离开,直接删去树上权值小于(min-k)的点即可

    对于查询操作,常规操作,不多说了

    最后还要求我们输出一个离开的人,我们记录实际加入过平衡树的点的数量,减去最后剩余的点的数量即可

    下面放代码

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cctype>
    #define ll long long
    #define gc getchar
    #define maxn 100005
    using namespace std;
    
    inline ll read(){
        ll a=0;int f=0;char p=gc();
        while(!isdigit(p)){f|=p=='-';p=gc();}
        while(isdigit(p)){a=(a<<3)+(a<<1)+(p^48);p=gc();}
        return f?-a:a;
    }int n,m,ans,sum;
    
    struct ahaha{
        int v,sz,cnt,ch[2];
    }t[maxn];int rt,tot,f[maxn];
    #define lc t[i].ch[0]
    #define rc t[i].ch[1]
    inline int get(int x){return x==t[f[x]].ch[1];}
    inline void update(int i){
        t[i].sz=t[i].cnt+t[lc].sz+t[rc].sz;
    }
    inline void clear(int i){
        t[i].v=t[i].sz=t[i].cnt=f[i]=0;
    }
    inline int newnode(int v){
        int i=++tot;t[i].v=v;
        t[i].sz=t[i].cnt=1;
        return i;
    }
    inline void rotate(int x){
        int y=f[x],z=f[y],k=get(x);
        f[x]=z;f[t[x].ch[k^1]]=y;f[y]=x;
        if(z)t[z].ch[y==t[z].ch[1]]=x;
        t[y].ch[k]=t[x].ch[k^1];t[x].ch[k^1]=y;
        update(y);update(x);
    }
    void Splay(int x,int tar){
        for(int y=f[x];(y=f[x])!=tar;rotate(x))
            if(f[y]!=tar)rotate(get(y)==get(x)?y:x);
        if(!tar)rt=x;
    }
    inline void insert(int v){
        int i=rt,k;
        if(!rt){rt=newnode(v);return;}
        while(1){
            if(v==t[i].v){
                ++t[i].cnt;
                Splay(i,0);return;
            }
            k=v>t[i].v;
            if(!t[i].ch[k]){
                t[i].ch[k]=newnode(v);f[t[i].ch[k]]=i;
                Splay(t[i].ch[k],0);return;
            }
            i=t[i].ch[k];
        }
    }
    int find(int v){
        int i=rt,sum=0;
        while(1){
            if(v<t[i].v){i=lc;if(!i)return sum;}
            else{
                sum+=t[lc].sz;
                if(!rc||v==t[i].v){
                    if(v>t[i].v)sum+=t[i].cnt;
                    Splay(i,0);return sum+1;
                }
                sum+=t[i].cnt;i=rc;
            }
        }
    }
    int find_k(int k){
        int i=rt;
        while(1){
            if(k<=t[lc].sz)i=lc;
            else{
                k-=t[lc].sz;
                if(k<=t[i].cnt){
                    Splay(i,0);
                    return t[i].v;
                }
                k-=t[i].cnt;i=rc;
            }
        }
    }
    inline void del(int v){
        find(v);int old=rt,i=t[rt].ch[0];
        if(t[rt].cnt!=1){--t[rt].cnt;--t[rt].sz;return;}
        if(t[rt].sz==1){clear(rt);rt=0;return;}
        if(!t[rt].ch[0]){rt=t[rt].ch[1];f[rt]=0;clear(old);return;}
        if(!t[rt].ch[1]){rt=t[rt].ch[0];f[rt]=0;clear(old);return;}
        while(rc)i=rc;Splay(i,0);
        t[rt].ch[1]=t[old].ch[1];f[t[old].ch[1]]=rt;
        clear(old);update(rt);
    }
    
    inline void solve_1(){
        int v=read();if(v<m)return;
        insert(v-sum);++ans;
    }
    inline void solve_2(){
        int x=read();
        sum+=x;
    }
    inline void solve_3(){
        int v=read();
        sum-=v;insert(m-sum);
        find(-100000000);
        int x=rt;find(m-sum);int y=rt;
        Splay(x,0);Splay(y,x);t[y].ch[0]=0;
        update(y);update(x);del(m-sum);
    }
    inline void solve_4(){
        int k=read();
        if(t[rt].sz-2<k){
            puts("-1");
            return;
        }
        printf("%d
    ",find_k(t[rt].sz-k)+sum);
    }
    
    char s[5];
    int main(){
        n=read();m=read();
        insert(100000000);insert(-100000000);
        while(n--){
            scanf("%s",s+1);
            switch(s[1]){
                case 'I':solve_1();break;
                case 'A':solve_2();break;
                case 'S':solve_3();break;
                case 'F':solve_4();break;
            }
        }
        ans-=t[rt].sz-2;
        printf("%d
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    PHP定时备份MySQL,mysqldump语法大全
    虚拟机拷贝之后,发现系统内的开机自启动的nginx,不能自启动了
    八:二叉搜索树的后序遍历
    配置Ubuntu开发环境
    poj 1147 Binary codes
    test
    Python标准库:内置函数reversed(seq)
    Matplotlib 工具包 使用教程索引
    6大设计原则(1):单一职责原则
    hdu 4104
  • 原文地址:https://www.cnblogs.com/hanruyun/p/10282542.html
Copyright © 2011-2022 走看看