3296: [NOI2004]郁闷的出纳员
时间限制: 1 Sec 内存限制: 128 MB题目描述
OIER公司是一家大型专业化软件公司,有着数以万计的员工。作为一名出纳员,我的任务之一便是统计每位员工的工资。
这本来是一份不错的工作,但是令人郁闷的是,我们的老板反复无常,经常调整员工的工资。
如果他心情好,就可能把每位员工的工资加上一个相同的量。
反之,如果心情不好,就可能把他们的工资扣除一个相同的量。
我真不知道除了调工资他还做什么其它事情。
工资的频繁调整很让员工反感,尤其是集体扣除工资的时候,一旦某位员工发现自己的工资已经低于了合同规定的工资下界,他就会立刻气愤地离开公司,并且再也不会回来了。
每位员工的工资下界都是统一规定的。
每当一个人离开公司,我就要从电脑中把他的工资档案删去,同样,每当公司招聘了一位新员工,我就得为他新建一个工资档案。
老板经常到我这边来询问工资情况,他并不问具体某位员工的工资情况,而是问现在工资第k多的员工拿多少工资。每当这时,我就不得不对数万个员工进行一次漫长的排序,然后告诉他答案。
好了,现在你已经对我的工作了解不少了。正如你猜的那样,我想请你编一个工资统计程序。怎么样,不是很困难吧?
输入
输出
样例输入
9 10
I 60
I 70
S 50
F 2
I 30
S 15
A 5
F 1
F 2
样例输出
10
20
-1
2
提示
I命令的条数不超过100000
A命令和S命令的总条数不超过100
F命令的条数不超过100000
每次工资调整的调整量不超过1000
新员工的工资不超过100000
只要在进入名单的时候加上之前的那些人已经变化的工资就好了
注意此题有坑,其实也是我自己写得有漏洞,以后一定注意了。
在对树进行操作的时候应该先考虑一下树是否为空,并且这个题目有毒
(它并没有说那种起始工资低于最低水平的不算入离开的人里阿,委屈。)
Code:
#include<iostream>
#include<cstdio>
#include<cstdlib>
using namespace std;
const int Max = 100005;
const int INF = 0x3f3f3f3f;
struct node{
int num, sum;
int lc, rc, h;
}Tr[Max];
int cnt, Pre, Suc;
void getint(int & num){
char c; int flg = 1; num = 0;
while((c = getchar()) < '0' || c > '9') if(c == '-') flg = -1;
while(c >= '0' && c <= '9') { num = num * 10 + c - 48; c = getchar();}
num *= flg;
}
int max(int a, int b){ return a < b ? b : a;}
int min(int a, int b){ return a < b ? a : b;}
void pushup(int & r){
Tr[r].sum = Tr[Tr[r].lc].sum + Tr[Tr[r].rc].sum + 1;
Tr[r].h = max(Tr[Tr[r].lc].h, Tr[Tr[r].rc].h) + 1;
}
int zig(int r){
int t = Tr[r].lc;
Tr[r].lc = Tr[t].rc, Tr[t].rc = r;
pushup(r), pushup(t);
return t;
}
int zag(int r){
int t = Tr[r].rc;
Tr[r].rc = Tr[t].lc, Tr[t].lc = r;
pushup(r), pushup(t);
return t;
}
int zigzag(int r){
Tr[r].rc = zig(Tr[r].rc);
return zag(r);
}
int zagzig(int r){
Tr[r].lc = zag(Tr[r].lc);
return zig(r);
}
void maintain(int & r){
if(Tr[Tr[r].lc].h == Tr[Tr[r].rc].h + 2){
int t = Tr[r].lc;
if(Tr[Tr[t].lc].h == Tr[Tr[r].rc].h + 1) r = zig(r);
else if(Tr[Tr[t].rc].h == Tr[Tr[r].rc].h + 1) r = zagzig(r);
}
else if(Tr[Tr[r].rc].h == Tr[Tr[r].lc].h + 2){
int t = Tr[r].rc;
if(Tr[Tr[t].rc].h == Tr[Tr[r].lc].h + 1) r = zag(r);
else if(Tr[Tr[t].lc].h == Tr[Tr[r].lc].h + 1) r = zigzag(r);
}
pushup(r);
}
void Insert(int & r, int val){
if(! r){
r = ++ cnt;
Tr[r].num = val;
Tr[r].h = Tr[r].sum = 1;
return ;
}
if(val < Tr[r].num) Insert(Tr[r].lc, val);
else Insert(Tr[r].rc, val);
maintain(r);
}
int Dele(int & r, int val){
int tx;
if(Tr[r].num == val || (val < Tr[r].num && ! Tr[r].lc) || ( val > Tr[r].num && ! Tr[r].rc)){
if(! Tr[r].lc || ! Tr[r].rc){
tx = Tr[r].num;
r = Tr[r].lc + Tr[r].rc;
return tx;
}
else Tr[r].num = Dele(Tr[r].lc, val);
}
else {
if(val < Tr[r].num) tx = Dele(Tr[r].lc, val);
else tx = Dele(Tr[r].rc, val);
}
maintain(r);
return tx;
}
int Srank(int r, int val){
if(! r) return 0;
if(val <= Tr[r].num) return Srank(Tr[r].lc, val);
else return Tr[Tr[r].lc].sum + 1 + Srank(Tr[r].rc, val);
}
int Frank(int r, int val){
if(Tr[Tr[r].lc].sum + 1 == val) return Tr[r].num;
if(Tr[Tr[r].lc].sum + 1 < val) return Frank(Tr[r].rc, val - Tr[Tr[r].lc].sum - 1);
else return Frank(Tr[r].lc, val);
}
int main(){
char ord[10];
int T, Min, x, R = 0, Delta = 0, Leave = 0, Low, In = 0;
getint(T), getint(Min);
while(T --){
scanf("%s", ord);
getint(x);
switch(ord[0]){
case 'I':{
if(x >= Min)
Insert(R, x - Delta), ++ In;
break;
}
case 'A':{
Delta += x;
break;
}
case 'S':{
Delta -= x;
if(R) {
Low = Frank(R, 1);
while(R && Low + Delta < Min)
++ Leave, -- In, Dele(R, Low), Low = Frank(R, 1);
if(! R) Delta = 0;
}
break;
}
case 'F':{
if(x > In) puts("-1");
else printf("%d\n", Frank(R, In - x + 1) + Delta);
break;
}
}
}
printf("%d\n", Leave);
return 0;
}