题目描述请见原题。
分析
看完题目就觉得是个裸的数据结构题。由于最近才学了Treap的基本操作,就顺便当练手。
首先需要会Treap的基本操作。
第一类操作,由于这个题对员工编号没有要求,所以直接插入一个即可。
第二、三类,可以设一个delt,直接对delt加减即可。由于删除操作不会超过100次,而员工人数又不会超过100000,所以每次减工资后,直接暴力枚举删除即可。
第四类常规操作了。
容易出错的地方:
1,插入时,先判断是不是小于MIN,小于就continue。然后减去一个delt之后再插入,便于操作。
2,删除时,建议做一个后序DFS,也就是先检查儿子,再检查自己。因为旋转操作对父亲是没有影响的。每次一定要从root开始删除,因为整个树的大小在改变。
3,输出时,记得加上一个delt。
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cstdlib>
using namespace std;
const int MAXN=100005;
int val[MAXN];
int ch[MAXN][2];
int cnt[MAXN];
int size[MAXN];
int prior[MAXN];
int rt=0,np=0,MIN,N,delt=0,tot=0,leave=0;
void update(int now) {size[now] = size[ch[now][0]] + size[ch[now][1]] + cnt[now];}
void rotate(int &now,int dir)
{
int son = ch[now][dir^1];
ch[now][dir^1] = ch[son][dir];
ch[son][dir] = now;
update(now);
update(now = son);
}
void insert(int &now, int num)
{
if(!now)
{
now = ++np;
cnt[now] = size[now] = 1;
val[now] = num;
prior[now] = rand();
return;
}
size[now]++;
if(val[now] == num) {cnt[now]++; return;}
int d = num < val[now];
insert(ch[now][d], num);
if(prior[ch[now][d]] < prior[now]) rotate(now, d^1);
}
void remove(int &now, int num)
{
if(!now) return;
if(val[now] == num)
{
if(cnt[now] > 1) {cnt[now]--; size[now]--; return;}
if(!ch[now][0] || !ch[now][1]) {now = ch[now][0] + ch[now][1]; return;}
int d = prior[ch[now][1]] < prior[ch[now][0]];
rotate(now, d^1); remove(now, num);
return;
}
size[now]--;
int d = num < val[now];
remove(ch[now][d], num);
}
void check(int now)
{
if(ch[now][0]) check(ch[now][0]);
if(ch[now][1]) check(ch[now][1]);
if(val[now] + delt < MIN)
{
int t=cnt[now];
while(t--) { tot--;leave++; remove(rt, val[now]); }
}
}
int kth(int now, int k)
{
while(now)
{
if(k <= size[ch[now][0]]) now = ch[now][0];
else if(k > size[ch[now][0]] + cnt[now]) k -= size[ch[now][0]] + cnt[now], now = ch[now][1];
else return val[now];
}
}
int main()
{
scanf("%d%d", &N, &MIN);
char op;
int x;
while(N--)
{
scanf("%s%d", &op, &x);
if(op == 'I') {if(x<MIN) continue; tot++; insert(rt, x-delt);}
else if(op == 'A') delt += x;
else if(op == 'S') {delt -= x; check(rt);}
else {if(tot<x) printf("-1\n"); else printf("%d\n", kth(rt, x) + delt);}
}
printf("%d",leave);
return 0;
}