zoukankan      html  css  js  c++  java
  • Luogu P1486 [NOI2004]郁闷的出纳员(平衡树)

    P1486 [NOI2004]郁闷的出纳员

    题意

    题目描述

    (OIER)公司是一家大型专业化软件公司,有着数以万计的员工。作为一名出纳员,我的任务之一便是统计每位员工的工资。这本来是一份不错的工作,但是令人郁闷的是,我们的老板反复无常,经常调整员工的工资。如果他心情好,就可能把每位员工的工资加上一个相同的量。反之,如果心情不好,就可能把他们的工资扣除一个相同的量。我真不知道除了调工资他还做什么其它事情。

    工资的频繁调整很让员工反感,尤其是集体扣除工资的时候,一旦某位员工发现自己的工资已经低于了合同规定的工资下界,他就会立刻气愤地离开公司,并且再也不会回来了。每位员工的工资下界都是统一规定的。每当一个人离开公司,我就要从电脑中把他的工资档案删去,同样,每当公司招聘了一位新员工,我就得为他新建一个工资档案。

    老板经常到我这边来询问工资情况,他并不问具体某位员工的工资情况,而是问现在工资第k多的员工拿多少工资。每当这时,我就不得不对数万个员工进行一次漫长的排序,然后告诉他答案。

    好了,现在你已经对我的工作了解不少了。正如你猜的那样,我想请你编一个工资统计程序。怎么样,不是很困难吧?

    如果某个员工的初始工资低于最低工资标准,那么将不计入最后的答案内

    输入输出格式

    输入格式:

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

    接下来的(n)行,每行表示一条命令。命令可以是以下四种之一:

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

    _(下划线)表示一个空格,(I)命令、(A)命令、(S)命令中的(k)是一个非负整数,(F)命令中的(k)是一个正整数。

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

    输出格式:

    输出文件的行数为(F)命令的条数加一。

    对于每条(F)命令,你的程序要输出一行,仅包含一个整数,为当前工资第(k)多的员工所拿的工资数,如果k大于目前员工的数目,则输出(-1)

    输出文件的最后一行包含一个整数,为离开公司的员工的总数。

    输入输出样例

    输入样例#1:

    9 10
    I 60
    I 70
    S 50
    F 2
    I 30
    S 15
    A 5
    F 1
    F 2
    

    输出样例#1:

    10
    20
    -1
    2
    

    说明

    (I)命令的条数不超过(100000)

    (A)命令和(S)命令的总条数不超过(100)

    (F)命令的条数不超过(100000)

    每次工资调整的调整量不超过(1000)

    新员工的工资不超过(100000)

    思路

    在每次(A)(S)的时候,我们不去把每个人的工资更新,而是记录当前所有人的工资已经增加/减少了多少。假设当前已经变化了(delta)数量的工资,(delta)为正即为增加工资,(delta)为负即为减少工资,那么当我们新增一个工资为(k)的新员工时,就新增一个(k-delta)的档案,来消除他没有经历的工资变化。删除员工时,只删除当前工资小于(min-delta)的,查询第(k)大时,输出员工工资和(delta)的和,这样我们不用更新每个人的工资,照样可以完成所有操作。在这里,我用的是(fhq Treap)来完成各个操作。

    AC代码

    #include<bits/stdc++.h>
    using namespace std;
    const int MAXN=2e5+5;
    int n,salary,delta,cnt,rt,ans;
    struct Node
    {
        int sz,rnd,val;
        int ls,rs;
        #define sz(a) tree[a].sz
        #define rnd(a) tree[a].rnd
        #define val(a) tree[a].val
        #define ls(a) tree[a].ls
        #define rs(a) tree[a].rs
    }tree[MAXN];
    void update(int p){sz(p)=sz(ls(p))+sz(rs(p))+1;}
    int new_node(int k)
    {
        sz(++cnt)=1;
        rnd(cnt)=rand();
        val(cnt)=k;
        ls(cnt)=rs(cnt)=0;
        return cnt;
    }
    int merge(int x,int y)
    {
        if(!x||!y) return x+y;
        if(rnd(x)<rnd(y))
        {
            rs(x)=merge(rs(x),y);
            update(x);
            return x;
        }
        else
        {
            ls(y)=merge(x,ls(y));
            update(y);
            return y;
        }
    }
    void split(int now,int k,int &x,int &y)
    {
        if(!now) x=y=0;
        else
        {
            if(val(now)>=k)
            {
                x=now;
                split(rs(now),k,rs(x),y);
            }
            else
            {
                y=now;
                split(ls(now),k,x,ls(y));
            }
            update(now);
        }
    }
    int kth(int now,int k)
    {
        if(k==sz(ls(now))+1) return val(now);
        if(sz(ls(now))>=k) return kth(ls(now),k);
        else return kth(rs(now),k-sz(ls(now))-1);
    }
    int read()
    {
        int re=0;char ch=getchar();
        while(!isdigit(ch)) ch=getchar();
        while(isdigit(ch)) re=(re<<3)+(re<<1)+ch-'0',ch=getchar();
        return re;
    }
    char readc()
    {
        char ch=getchar();
        while(!isalpha(ch)) ch=getchar();
        return ch;
    }
    int main()
    {
        srand(time(0));
        n=read(),salary=read();
        while(n--)
        {
            char opt=readc();int k=read();
            if(opt=='I')
            {
                if(k<salary) continue;
                k-=delta;
                int x,y;
                split(rt,k,x,y);
                rt=merge(merge(x,new_node(k)),y);
            }
            else if(opt=='A') delta+=k;
            else if(opt=='S')
            {
                delta-=k;
                int x,y;
                split(rt,salary-delta,x,y);
                rt=x,ans+=sz(y);
            }
            else if(opt=='F')
            {
                if(k>sz(rt)) printf("%d
    ",-1);
                else printf("%d
    ",kth(rt,k)+delta);
            }
        }
        printf("%d",ans);
        return 0;
    }
    
  • 相关阅读:
    ASP.NET使用Coolite.Ext.Web.dll,显示ext"未定义"的解决方法
    浏览器引擎模式与DOCTYPE
    MVC 参数如何自动绑定数组对象
    IIS7.5 配置 PHP
    TFSDeleteProject:删除团队项目
    自动生成存储过程一
    如何更新ntext字段信息
    清除所有默认样式的CSS代码
    自定义动作过滤器属性
    IE9点击别的网页弹出空白页
  • 原文地址:https://www.cnblogs.com/coder-Uranus/p/9887161.html
Copyright © 2011-2022 走看看