【NOI2004】郁闷的出纳员 |
Time Limit:10000MS Memory Limit:65536K
Total Submit:469 Accepted:179
Case Time Limit:2000MS
Description
OIER公司是一家大型专业化软件公司,有着数以万计的员工。作为一名出纳员,我的任务之一便是统计每位员工的工资。这本来是一份不错的工作,但是令人郁闷的是,我们的老板反复无常,经常调整员工的工资。如果他心情好,就可能把每位员工的工资加上一个相同的量。反之,如果心情不好,就可能把他们的工资扣除一个相同的量。我真不知道除了调工资他还做什么其它事情。
工资的频繁调整很让员工反感,尤其是集体扣除工资的时候,一旦某位员工发现自己的工资已经低于了合同规定的工资下界,他就会立刻气愤地离开公司,并且再也不会回来了。每位员工的工资下界都是统一规定的。每当一个人离开公司,我就要从电脑中把他的工资档案删去,同样,每当公司招聘了一位新员工,我就得为他新建一个工资档案。
老板经常到我这边来询问工资情况,他并不问具体某位员工的工资情况,而是问现在工资第k多的员工拿多少工资。每当这时,我就不得不对数万个员工进行一次漫长的排序,然后告诉他答案。
好了,现在你已经对我的工作了解不少了。正如你猜的那样,我想请你编一个工资统计程序。怎么样,不是很困难吧?
Input
第一行有两个非负整数n和min。n表示下面有多少条命令,min表示工资下界。
接下来的n行,每行表示一条命令。命令可以是以下四种之一:
_(下划线)表示一个空格,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
Source
xinyue
WA代码:
#include <cstdio> #include <iostream> using namespace std; #define keyTree (ch[ ch[root][1] ][0]) #define inf 10000000 const int maxn = 222222; int min1; int size[maxn]; int ch[maxn][2]; int pre[maxn]; int root , top1; /*这是题目特定变量*/ int num[maxn]; int val[maxn]; int add[maxn]; inline void push_down(int x) {/*这是题目特定函数*/ if(add[x]) { val[x] += add[x]; add[ ch[x][0] ] += add[x]; add[ ch[x][1] ] += add[x]; add[x] = 0; } } //把孩子状态更新上来 inline void push_up(int x) { size[x] = 1 + size[ ch[x][0] ] + size[ ch[x][1] ]; /*这是题目特定函数*/ } void Inorder(int r) { push_down(r); if(r==0)return; Inorder(ch[r][0]); printf("%d ",val[r]); Inorder(ch[r][1]); push_up(r); } inline void Rotate(int x,int f) { int y = pre[x]; push_down(y); push_down(x); ch[y][!f] = ch[x][f]; pre[ ch[x][f] ] = y; pre[x] = pre[y]; if(pre[x]) ch[ pre[y] ][ ch[pre[y]][1] == y ] = x; ch[x][f] = y; pre[y] = x; push_up(y); } inline void Splay(int x,int goal) { push_down(x); while(pre[x] != goal) { if(pre[pre[x]] == goal) { Rotate(x , ch[pre[x]][0] == x); } else { int y = pre[x] , z = pre[y]; int f = (ch[z][0] == y); if(ch[y][f] == x) { Rotate(x , !f) , Rotate(x , f); } else { Rotate(y , f) , Rotate(x , f); } } } push_up(x); if(goal == 0) root = x; } inline void RotateTo(int k,int goal) {//把第k位的数转到goal下边 int x = root; push_down(x); while(size[ ch[x][0] ] != k) { if(k < size[ ch[x][0] ]) { x = ch[x][0]; } else { k -= (size[ ch[x][0] ] + 1);//多减去1,所以k+1位 x = ch[x][1]; } push_down(x); } Splay(x,goal); } inline void NewNode(int &x,int c,int fa) { x = ++top1; ch[x][0] = ch[x][1] = pre[x] = 0; size[x] = 1; pre[x]=fa; val[x] = c;/*这是题目特定函数*/ add[x] = 0; } //把延迟标记推到孩子 int Get_Kth(int r,int k){ push_down(r); int t=size[ch[r][0]]+1; if(t==k) return r; if(t>k) return Get_Kth(ch[r][0],k); else return Get_Kth(ch[r][1],k-t); } int ins(int &x,int data,int fa) { if(x==0)NewNode(x,data,fa); else { size[x]++; ins(ch[x][val[x]<data],data,x); Splay(ch[x][val[x]<data],0); } return 1; } inline void init(int n) {/*这是题目特定函数*/ ch[0][0] = ch[0][1] = pre[0] = size[0] = 0; add[0] = 0; root = top1 = 0; } int Get_pre(int &r,int y,int k) { if(r==0) { if(y==0) return inf; return y; } push_down(r); if(k>val[r])return Get_pre(ch[r][1],r,k); else return Get_pre(ch[r][0],y,k); } int Delete() { int x=Get_pre(root,0,min1); if(x==inf) { return 0; } Splay(x,0); //int y=Get_Min(ch[root][1]); //Splay(y,root); push_up(ch[root][0]); int p=size[ch[root][0]]+1; root=ch[root][1]; pre[ch[root][1]]=0; return p; } /*更新*/ inline void update(int c) {/*这是题目特定函数*/ add[root] += c; push_down(root); } int main() { int n ,k; int a,b; while(scanf("%d%d",&n,&min1)!=EOF) { init(n); a=0;b=0; //spt.debug(); while(n--) { char op[2]; scanf("%s",op); if(op[0] == 'I') { scanf("%d",&k); if(k>=min1) { b++; ins(root,k,0); } } else if(op[0] == 'A') { scanf("%d",&k); update(k); } else if(op[0] == 'S') { scanf("%d",&k); update(-k); int p=Delete(); a+=p; b-=p; } else if(op[0] == 'F') { scanf("%d",&k); if(k>b) printf("-1\n"); else { int x=Get_Kth(root,b+1-k); printf("%d\n",val[x]); } } } printf("%d\n",a); } return 0; }