您的位置:首页 > 其它

[NOI2004]郁闷的出纳员

2017-12-25 15:41 323 查看
Description

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

Input



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;

Source

思路

splay,每一次工资的增加和减少可以不对每一个值进行修改,而是记录一个全局变量,加入员工时只要加入实际工资减去增加量。底下会有注释。

代码

#include <cstdio>

const int maxn=100000;

int minn,leave,add;//leave是离开的人数,add是工资的增长量

struct splay_tree
{
int root,tot,fa[maxn+10],son[2][maxn+10],size[maxn+<
10a91
span class="hljs-number">10],val[maxn+10];

inline int t(int x)
{
return son[1][fa[x]]==x;
}

inline int updata(int x)
{
size[x]=1;
if(son[0][x])
{
size[x]+=size[son[0][x]];
}
if(son[1][x])
{
size[x]+=size[son[1][x]];
}
return 0;
}

inline int rotate(int x)
{
int k=t(x),f=fa[x];
if(fa[f])
{
son[t(f)][fa[f]]=x;
}
fa[x]=fa[f];
if(son[!k][x])
{
fa[son[!k][x]]=f;
}
son[k][f]=son[!k][x];
fa[f]=x;
son[!k][x]=f;
updata(f);
updata(x);
return 0;
}

inline int splay(int x,int c)
{
while(fa[x]!=c)
{
int f=fa[x];
if(fa[f]==c)
{
rotate(x);
}
else if(t(x)==t(f))
{
rotate(f);
rotate(x);
}
else
{
rotate(x);
rotate(x);
}
}
if(!c)
{
root=x;
}
return 0;
}

inline int insert(int now,int x)
{
int p=(val[now]<x);
if(!son[p][now])
{
son[p][now]=tot;
fa[tot]=now;
updata(now);
return 0;
}
insert(son[p][now],x);
updata(now);
return 0;
}

inline int ins(int x)
{
if(x<minn)
{
return 0;
}
x-=add;
++tot;
val[tot]=x;
size[tot]=1;
if(!root)
{
root=tot;
return 0;
}
int now=root;
if(now)
{
insert(now,x);
}
splay(tot,0);
return 0;
}

int maintain(int x)//维护离开公司的人数
{
if(val[x]+add<minn)//这个人要离开公司了,把他的左子树和自己删掉
{
++leave;
if(son[0][x])
{
leave+=size[son[0][x]];
son[0][x]=0;
}
if(son[1][x])
{
maintain(son[1][x]);
}
if(fa[x])
{
son[t(x)][fa[x]]=son[1][x];
updata(fa[x]);//更新x的父亲,一定是在修复右儿子之后的
}
else
{
root=son[1][x];
}
if(son[1][x])
{
fa[son[1][x]]=fa[x];
}
}
else//如果不要,那么在左子树中寻找要离开公司的人
{
if(son[0][x])
{
maintain(son[0][x]);
}
updata(x);//修复自己
}
return 0;
}

int kth(int x,int k)
{
if(size[x]<k)
{
return -1;
}
else if(size[son[1][x]]+1==k)
{
splay(x,0);
return x;
}
else if(size[son[1][x]]+1<k)
{
return kth(son[0][x],k-size[son[1][x]]-1);
}
else
{
return kth(son[1][x],k);
}
}
};

splay_tree st;
int n,a;
char s[10];

int main()
{
scanf("%d%d",&n,&minn);
while(n--)
{
scanf("%s%d",s,&a);
if(s[0]=='I')
{
st.ins(a);
}
else if(s[0]=='A')
{
add+=a;
}
else if(s[0]=='S')
{
add-=a;
if(st.root)
{
st.maintain(st.root);
}
}
else
{
if(st.size[st.root]<a)
{
puts("-1");
}
else
{
printf("%d\n",st.val[st.kth(st.root,a)]+add);
}
}
}
printf("%d\n",leave);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: