P1486 郁闷的出纳员
题目描述
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
模版题,唯一的创新就是用一个cal记录加工资与扣工资,加t元就cal-=t。扣工资时就先处理好cal再把cal插到BST里面,旋转到根,看他左侧子树大小,然后把左子树删掉。
不过有可能中间的时候公司里没有人,这是再插入人就要重新建树了。
1 #include<cstdio> 2 #include<iostream> 3 #include<string> 4 using namespace std; 5 const int N=100005; 6 int F[N],lch[N],rch[N],key[N],size[N],num[N],root=0,sz=0,cnt=0; 7 inline void update(int x) 8 { 9 size[x]=num[x]; 10 if(lch[x]) size[x]+=size[lch[x]]; 11 if(rch[x]) size[x]+=size[rch[x]]; 12 } 13 inline void zig(int x) 14 { 15 int f=F[x],gf=F[f]; 16 F[f]=x; 17 F[x]=gf; 18 if(gf) 19 { 20 if(lch[gf]==f) lch[gf]=x; 21 else if(rch[gf]==f) rch[gf]=x; 22 } 23 lch[f]=rch[x]; 24 F[rch[x]]=f; 25 rch[x]=f; 26 update(f); 27 update(x); 28 } 29 inline void zag(int x) 30 { 31 int f=F[x],gf=F[f]; 32 F[f]=x; 33 F[x]=gf; 34 if(gf) 35 { 36 if(lch[gf]==f) lch[gf]=x; 37 else if(rch[gf]==f) rch[gf]=x; 38 } 39 rch[f]=lch[x]; 40 F[lch[x]]=f; 41 lch[x]=f; 42 update(f); 43 update(x); 44 } 45 inline void splay(int x) 46 { 47 int f,gf; 48 while(F[x]!=0) 49 { 50 f=F[x]; 51 gf=F[f]; 52 if(gf==0) 53 { 54 if(x==lch[f]) zig(x); 55 else if(x==rch[f]) zag(x); 56 break; 57 } 58 if(f==lch[gf]&&x==lch[f]) {zig(f);zig(x);} 59 else if(f==rch[gf]&&x==rch[f]) {zag(f);zag(x);} 60 else if(f==rch[gf]&&x==lch[f]) {zig(x);zag(x);} 61 else {zag(x);zig(x);} 62 } 63 root=x; 64 } 65 inline int find(int x) 66 { 67 int p=root; 68 while(key[p]!=x) 69 { 70 if(key[p]>x) 71 { 72 if(lch[p]) p=lch[p]; 73 else break; 74 } 75 if(key[p]<x) 76 { 77 if(rch[p]) p=rch[p]; 78 else break; 79 } 80 } 81 return p; 82 } 83 inline void ins(int x) 84 { 85 if(size[root]==0) 86 { 87 key[++sz]=x; 88 size[sz]=1; 89 num[sz]=1; 90 root=sz; 91 F[sz]=0; 92 return; 93 } 94 int p=find(x); 95 if(key[p]!=x) 96 { 97 key[++sz]=x; 98 num[sz]=0; 99 F[sz]=p; 100 if(x<key[p]) lch[p]=sz; 101 else rch[p]=sz; 102 lch[sz]=rch[sz]=0; 103 p=sz; 104 } 105 num[p]++; 106 update(p); 107 update(F[p]); 108 splay(p); 109 } 110 inline void del() 111 { 112 int old=root; 113 lch[old]=0; 114 num[old]--; 115 if(num[old]==0) 116 { 117 F[rch[old]]=0; 118 root=rch[old]; 119 } 120 update(root); 121 } 122 inline int findn(int x,int p) 123 { 124 int sr=size[rch[p]]; 125 if(x<=sr) return findn(x,rch[p]); 126 else if(sr<x&&x<=sr+num[p]) return key[p]; 127 else return findn(x-sr-num[p],lch[p]); 128 } 129 int main() 130 { 131 int n,m,t,Min,cal; 132 char c; 133 scanf("%d%d",&n,&Min); 134 cal=cnt=0; 135 for(int i=1;i<=n;i++) 136 { 137 scanf("\n%c%d",&c,&t); 138 if(c==‘I‘&&t>=Min) ins(t+cal); 139 else if(c==‘A‘) cal-=t; 140 else if(c==‘S‘) 141 { 142 cal+=t; 143 ins(cal+Min); 144 cnt+=size[lch[root]]; 145 del(); 146 } 147 else if(c==‘F‘) 148 { 149 if(size[root]<t) printf("-1\n"); 150 else printf("%d\n",(findn(t,root)-cal)); 151 } 152 } 153 printf("%d\n",cnt); 154 return 0; 155 }