题面
思路
看到题目的插入、删除和查询第 k 大操作,就想到了 Treap。
但是全部员工加减工资怎么办?仔细一看,这两种操作总条数不会超过 100,所以遍历整棵树更改数值就好了。
在增加工资的时候,一定不会有人离开。
在减少工资的时候,我们不断找工资底线 k 的前驱,如果它存在,就删除它。
最后的离开人数就是插入操作的次数减去最后的人数。
代码
#include<bits/stdc++.h>
using namespace std;
struct node{
long long x,y,l,r,size,cnt;
};
node s[1000001];
long long n,q,top=0,cnt=0,len=0,k;
long long root=0;
void dfs(long long x,int k){
if (!x){
return;
}
s[x].x+=k;
dfs(s[x].l,k);
dfs(s[x].r,k);
}
void update(long long x){
s[x].size=s[s[x].l].size+s[s[x].r].size+s[x].cnt;
}
void rotr(long long &x){
long long l=s[x].l;
s[x].l=s[l].r;
s[l].r=x;
s[l].size=s[x].size;
update(x);
x=l;
}
void rotl(long long &x){
long long r=s[x].r;
s[x].r=s[r].l;
s[r].l=x;
s[r].size=s[x].size;
update(x);
x=r;
}
void add(long long &x,long long data){
if (!x){
x=++top;
s[x].x=data;
s[x].y=rand()%19260817;
s[x].cnt=1;
s[x].size=1;
s[x].l=0;
s[x].r=0;
return;
}
s[x].size++;
if (s[x].x==data){
s[x].cnt++;
}else if (data<s[x].x){
add(s[x].l,data);
if (s[x].y>s[s[x].l].y){
rotr(x);
}
}else{
add(s[x].r,data);
if (s[x].y>s[s[x].r].y){
rotl(x);
}
}
}
void del(long long &x,long long data){
if (s[x].x==data){
if (s[x].cnt>1){
s[x].cnt--;
s[x].size--;
return;
}
if (!s[x].l||!s[x].r){
x=s[x].l+s[x].r;
return;
}
if (s[s[x].l].y<s[s[x].r].y){
rotr(x);
del(x,data);
}else{
rotl(x);
del(x,data);
}
return;
}
s[x].size--;
if (data<s[x].x){
del(s[x].l,data);
}else{
del(s[x].r,data);
}
}
long long pre(long long data){
long long now=root,res=-2147483647;
while (now){
if (s[now].x<data){
res=s[now].x;
now=s[now].r;
}else{
now=s[now].l;
}
}
return res;
}
long long nxt(long long data){
long long now=root,res=2147483647;
while (now){
if (s[now].x>data){
res=s[now].x;
now=s[now].l;
}else{
now=s[now].r;
}
}
return res;
}
long long querykth(long long k){
long long now=root;
while (now){
if (s[s[now].l].size<k&&s[s[now].l].size+s[now].cnt>=k){
return s[now].x;
}
if (s[s[now].l].size>=k){
now=s[now].l;
}else{
k-=s[s[now].l].size+s[now].cnt;
now=s[now].r;
}
}
return 0;
}
long long queryrank(long long data){
long long now=root,res=0;
while (now){
if (data==s[now].x){
return res+s[s[now].l].size+1;
}
if (data<s[now].x){
now=s[now].l;
}else{
res+=s[s[now].l].size+s[now].cnt;
now=s[now].r;
}
}
return res;
}
void check(){
int x=pre(k);
while (x<k&&x!=-2147483647){
del(root,x);
len--;
x=pre(k);
}
}
int main(){
srand(time(0));
cin>>q>>k;
string t;
long long x;
while (q--){
cin>>t>>x;
if (t=="I"){
if (x<k){
continue;
}
len++;
cnt++;
add(root,x);
}
if (t=="A"){
dfs(root,x);
}
if (t=="S"){
dfs(root,-x);
check();
}
if (t=="F"){
if (x>len){
cout<<"-1"<<endl;
continue;
}
cout<<querykth(len-x+1)<<endl;
}
}
cout<<cnt-len;
}