 /**//*
题意:实现对所有员工工资加x、减x(如果减了后发现低于最低工资,则离开)
并查询第k大的工资
这里用树状数组
插入容易实现
删除时注意for(int i = 1;;i++) i从小到大,则c[i]存的就是工资为i时的人数了!
还有是整个线段操作,所以用delta标记,会快很多!!
插入时,就插入 x-delta+INF
加上INF避免变为负数了~
还有findK() 其实是用二分不断逼近 保持着cnt<K 则最后ans+1即为答案了
*/
#include<cstdio>
#include<cstring>

const int MAX_VAL = 300000,INF = 100000;

int c[MAX_VAL+5];
int delta;

 inline int lowbit(int x) {return x&(-x);}

int sum(int p)
  {
int ans = 0;
while(p>0)
 {
ans+=c[p];
p-=lowbit(p);
}
return ans;
}
void update(int p,int x)
  {
while(p<=MAX_VAL)
 {
c[p]+=x;
p+=lowbit(p);
}
}
int findK(int K)
  {
int ans = 0,cnt = 0;
for(int i=19;i>=0;i--)
 {
ans+=(1<<i);
if(ans>=MAX_VAL||cnt+c[ans]>=K)ans-=(1<<i);
else cnt+=c[ans];
}
return ans+1;
}
int main()
  {
int Q,Min;
while(~scanf("%d%d",&Q,&Min))
 {
memset(c,0,sizeof(c));
delta = 0;
int tot = 0,del = 0;
while(Q--)
 {
char op;
int x;
scanf(" %c%d",&op,&x);
 if(op=='I') {
if(x<Min)continue;
update(x-delta+INF,1);
tot++;
}
else if(op=='S')
 {
delta-=x;
int tmp = sum(Min-1-delta+INF);
tot-=tmp;
del+=tmp;
for(int i=1;i<=Min-1-delta+INF;i++)
 {
if(c[i]==0)continue;
update(i,-c[i]);
//因为是从小到大删除,这时的c[i]其实就是工资为i的实际人数!
}
}
else if(op=='A')delta+=x;
else
 {
if(x>tot)puts("-1");
else printf("%d\n",findK(tot-x+1)+delta-INF);
}
}
printf("%d\n",del);
}
return 0;
}
|
|
常用链接
随笔分类
Links
搜索
最新评论

|
|