cashier.in
输出文件:cashier.out
简单对比时间限制:1 s 内存限制:128 MB
【问题描述】
OIER公司是一家大型专业化软件公司,有着数以万计的员工。作为一名出纳员,我的任务之一便是统计每位员工的工资。这本来是一份不错的工 作,但是令人郁闷的是,我们的老板反复无常,经常调整员工的工资。如果他心情好,就可能把每位员工的工资加上一个相同的量。反之,如果心情不好,就可能把 他们的工资扣除一个相同的量。我真不知道除了调工资他还做什么其它事情。
工资的频繁调整很让员工反感,尤其是集体扣除工资的时候,一旦某位员工发现自己的工资已经低于了合同规定的工资下界,他就会立刻气愤地离 开公司,并且再也不会回来了。每位员工的工资下界都是统一规定的。每当一个人离开公司,我就要从电脑中把他的工资档案删去,同样,每当公司招聘了一位新员 工,我就得为他新建一个工资档案。
老板经常到我这边来询问工资情况,他并不问具体某位员工的工资情况,而是问现在工资第k多的员工拿多少工资。每当这时,我就不得不对数万个员工进行一次漫长的排序,然后告诉他答案。
好了,现在你已经对我的工作了解不少了。正如你猜的那样,我想请你编一个工资统计程序。怎么样,不是很困难吧?
【输入文件】
第一行有两个非负整数n和min。n表示下面有多少条命令,min表示工资下界。接下来的n行,每行表示一条命令。命令可以是以下四种之一:
_(下划线)表示一个空格,I命令、A命令、S命令中的k是一个非负整数,F命令中的k是一个正整数。 在初始时,可以认为公司里一个员工也没有。
【输出文件】
输出文件的行数为F命令的条数加一。
对于每条F命令,你的程序要输出一行,仅包含一个整数,为当前工资第k多的员工所拿的工资数,如果k大于目前员工的数目,则输出-1。
输出文件的最后一行包含一个整数,为离开公司的员工的总数。
【样例输入】
9 10
I 60
I 70
S 50
F 2
I 30
S 15
A 5
F 1
F 2
【样例输出】
10
20
-1
2
【约定】
题解:
对于每次工资的加减,如果加工资,让工资的下线MIN减去这个数,如果减工资,让工资的下线MIN加上这个数,就是用一种相对运动的思想。
再记录一个delta变量,来处理新加入的员工。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cstring> 5 #include<cmath> 6 #include<queue> 7 #include<vector> 8 #include<algorithm> 9 using namespace std; 10 typedef long long LL; 11 const LL maxn=100010; 12 char s[5]; 13 LL root,tot,N,MIN,sum,delta; 14 LL key[maxn],lc[maxn],rc[maxn],siz[maxn]; 15 void r_rotate(LL &rt){ 16 LL k=lc[rt]; 17 lc[rt]=rc[k]; 18 rc[k]=rt; 19 siz[k]=siz[rt]; 20 siz[rt]=siz[lc[rt]]+siz[rc[rt]]+1; 21 rt=k; 22 } 23 void l_rotate(LL &rt){ 24 LL k=rc[rt]; 25 rc[rt]=lc[k]; 26 lc[k]=rt; 27 siz[k]=siz[rt]; 28 siz[rt]=siz[lc[rt]]+siz[rc[rt]]+1; 29 rt=k; 30 } 31 void Maintain(LL &rt,bool flag){ 32 if(flag==false){ 33 if(siz[lc[lc[rt]]]>siz[rc[rt]]) r_rotate(rt); 34 else if(siz[rc[lc[rt]]]>siz[rc[rt]]){ 35 l_rotate(lc[rt]); 36 r_rotate(rt); 37 } 38 else return ; 39 } 40 else{ 41 if(siz[rc[rc[rt]]]>siz[lc[rt]]) l_rotate(rt); 42 else if(siz[lc[rc[rt]]]>siz[lc[rt]]){ 43 r_rotate(rc[rt]); 44 l_rotate(rt); 45 } 46 else return ; 47 } 48 Maintain(lc[rt],0); Maintain(rc[rt],1); 49 Maintain(rt,1); Maintain(rt,0); 50 } 51 void insert(LL &rt,LL v){ 52 if(rt==0){ 53 rt=++tot; 54 siz[rt]=1; 55 lc[rt]=rc[rt]=0; 56 key[rt]=v; 57 return ; 58 } 59 siz[rt]++; 60 if(v<=key[rt]) insert(lc[rt],v); 61 else insert(rc[rt],v); 62 Maintain(rt,1); Maintain(rt,0); 63 } 64 LL Delete(LL &rt,LL v){ 65 LL ans; 66 siz[rt]--; 67 if(v==key[rt]||(v<key[rt]&&lc[rt]==0)||(v>key[rt]&&rc[rt]==0)){ 68 ans=key[rt]; 69 if(lc[rt]==0||rc[rt]==0) rt=lc[rt]+rc[rt]; 70 else key[rt]=Delete(lc[rt],key[rt]+1); 71 return ans; 72 } 73 else if(v<key[rt]) ans=Delete(lc[rt],v); 74 else ans=Delete(rc[rt],v); 75 return ans; 76 } 77 LL select(LL &rt,LL k){ 78 if(k==siz[lc[rt]]+1) return key[rt]; 79 if(k<=siz[lc[rt]]) return select(lc[rt],k); 80 else return select(rc[rt],k-1-siz[lc[rt]]); 81 } 82 bool find(LL &rt,LL v){ 83 if(rt==0) return false; 84 else if(v==key[rt]) return true; 85 else if(v<key[rt]) return find(lc[rt],v); 86 else if(v>key[rt]) return find(rc[rt],v); 87 } 88 LL pred(LL &rt,LL v){ 89 if(rt==0) return v; 90 if(v<=key[rt]) return pred(lc[rt],v); 91 else{ 92 LL ans=pred(rc[rt],v); 93 if(ans==v) return key[rt]; 94 return ans; 95 } 96 } 97 void Clear(){ 98 for(;;){ 99 LL k=pred(root,MIN); 100 if(find(root,k)==true&&k<MIN) Delete(root,k),sum++; 101 else break; 102 } 103 } 104 int main(){ 105 scanf("%lld%lld",&N,&MIN); 106 for(LL i=1,tmp;i<=N;i++){ 107 scanf("%s%lld",s,&tmp); 108 if(s[0]=='I'){ 109 if(tmp-delta<MIN){ 110 continue; 111 } 112 insert(root,tmp-delta); 113 } 114 else if(s[0]=='A'){//增加工资 115 MIN-=tmp;//要求标准下降 116 delta+=tmp; 117 Clear(); 118 } 119 else if(s[0]=='S'){//减少工资 120 MIN+=tmp;//要求标准上升 121 delta-=tmp; 122 Clear(); 123 } 124 else{ 125 if(siz[root]<tmp) puts("-1"); 126 else printf("%lld\n",select(root,siz[root]-tmp+1)+delta); 127 } 128 } 129 printf("%lld\n",sum); 130 return 0; 131 }