【NOI2004】郁闷的出纳员(splay)

来源:互联网 发布:书法集字软件 编辑:程序博客网 时间:2024/05/22 12:32

题面

Description

OIER公司是一家大型专业化软件公司,有着数以万计的员工。作为一名出纳员,我的任务之一便是统计每位员工的工资。这本来是一份不错的工 作,但是令人郁闷的是,我们的老板反复无常,经常调整员工的工资。如果他心情好,就可能把每位员工的工资加上一个相同的量。反之,如果心情不好,就可能把 他们的工资扣除一个相同的量。我真不知道除了调工资他还做什么其它事情。
工资的频繁调整很让员工反感,尤其是集体扣除工资的时候,一旦某位员工发现自己的工资已经低于了合同规定的工资下界,他就会立刻气愤地离 开公司,并且再也不会回来了。每位员工的工资下界都是统一规定的。每当一个人离开公司,我就要从电脑中把他的工资档案删去,同样,每当公司招聘了一位新员 工,我就得为他新建一个工资档案。
老板经常到我这边来询问工资情况,他并不问具体某位员工的工资情况,而是问现在工资第k多的员工拿多少工资。每当这时,我就不得不对数万个员工进行一次漫长的排序,然后告诉他答案。
好了,现在你已经对我的工作了解不少了。正如你猜的那样,我想请你编一个工资统计程序。怎么样,不是很困难吧?

Input

第一行有两个非负整数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是一个正整数。 在初始时,可以认为公司里一个员工也没有。

Output

输出的行数为F命令的条数加一。
对于每条F命令,你的程序要输出一行,仅包含一个整数,为当前工资第k多的员工所拿的工资数,如果k大于目前员工的数目,则输出-1。
输出的最后一行包含一个整数,为离开公司的员工的总数。
不包括刚来就走的,初始工资低于最低工资的员工直接离开,不算入“离开公司的员工的总数”。

Sample Input

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

Sample Output

10
20
-1
2

Hint

数据范围:
I命令的条数不超过100000
A命令和S命令的总条数不超过100
F命令的条数不超过100000
每次工资调整的调整量不超过1000
新员工的工资不超过100000

题解

插入和查询操作都是splay最基础的操作,不解释了。。
注意一下插入,存一下当前工资的总的增加情况,插入的时候减一下
问题在于如何处理删除
那么,找到当前减去之后的能够满足条件的最少区间的后缀
将后缀旋转到根节点
很显然,当前根节点的左儿子就是要删去的节点
统计一下即可

#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<cmath>#include<queue>#include<vector>#include<algorithm>using namespace std;#define INF 1000000000#define MAX 110000int root;inline int read(){    register int x=0,t=1;    register char ch=getchar();    while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();    if(ch=='-'){t=-1;ch=getchar();}    while(ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();}    return x*t;}struct Node{    int ch[2];    int val;    int ff;    int cnt;    int size;}t[MAX];int tot,n,mm,ans,add;inline void pushup(int x){    t[x].size=t[t[x].ch[0]].size+t[t[x].ch[1]].size+t[x].cnt;}inline void rotate(int x){    int y=t[x].ff;    int z=t[y].ff;    int k=(x==t[y].ch[1]);    t[z].ch[y==t[z].ch[1]]=x;    t[x].ff=z;    t[y].ch[k]=t[x].ch[k^1];   t[t[x].ch[k^1]].ff=y;    t[x].ch[k^1]=y;            t[y].ff=x;    pushup(y);pushup(x);}inline void splay(int x,int goal){    while(t[x].ff!=goal)    {        int y=t[x].ff;        int z=t[y].ff;        if(z!=goal)            (t[z].ch[0]==y)^(t[y].ch[0]==x)?rotate(x):rotate(y);        rotate(x);    }    if(goal==0)root=x;}inline void insert(int x){    int u=root,ff=0;    while(u&&t[u].val!=x)    {        ff=u;        u=t[u].ch[x>t[u].val];    }    if(u)t[u].cnt++;    else    {        u=++tot;        if(ff)t[ff].ch[x>t[ff].val]=u;        t[u].ch[0]=t[u].ch[1]=0;        t[u].val=x;        t[u].cnt=1;        t[u].size=1;        t[u].ff=ff;    }    splay(u,0);}inline void find(int x){    int u=root;    if(!u)return;    while(t[u].ch[x>t[u].val]&&t[u].val!=x)        u=t[u].ch[x>t[u].val];    splay(u,0);}inline int Next(int x,int f){    find(x);    int u=root;    if(t[u].val>=x&&f)return u;    if(t[u].val<=x&&!f)return u;    u=t[u].ch[f];    while(t[u].ch[f^1])u=t[u].ch[f^1];    return u;}inline int kth(int x){    int u=root;    if(t[u].size<x||x<=0)return -INF;    while(233)    {        int y=t[u].ch[0];        if(t[y].size+t[u].cnt<x)        {            x-=t[y].size+t[u].cnt;            u=t[u].ch[1];        }        else            if(t[y].size>=x)                u=y;            else                return t[u].val;    }}int main(){    insert(+INF);    scanf("%d%d",&n,&mm);    int peo=0;    while(n--)    {        int x;char ch[3];        scanf("%s%d",ch,&x);        if(ch[0]=='I')        {            if(x<mm);            else            {                insert(x-add);                peo++;            }        }        if(ch[0]=='A')            add+=x;        if(ch[0]=='S')        {            add-=x;            int gg=Next(mm-add,1);            splay(gg,0);            ans+=t[t[root].ch[0]].size;            peo-=t[t[root].ch[0]].size;            t[t[root].ch[0]].size=t[t[root].ch[0]].cnt=0;            t[root].ch[0]=0;t[0].size=0;            pushup(root);        }        if(ch[0]=='F')        {            int gg=kth(peo-x+1);            printf("%d\n",gg==-INF?-1:(gg+add));        }    }    printf("%d\n",ans);    return 0;}
阅读全文
0 0
原创粉丝点击