#include<cstdio>
#include<stdlib.h>
#include<iostream>
const int N=1e5+11,INF=0x7f7f7f7f;
struct Treap{
int val,dat;
int l,r;
int cnt,size;
}a[N];
int tot,root,p_d,p_i;//p_d是总共删除了多少个结点,内置在delete函数内的一个计数器,p_i是总共加入了多少个员工
int n,min;
int td; //td是总共全体员工上调/扣除的工资
int New(int val){
a[++tot].val=val;
a[tot].dat=rand();
a[tot].cnt=a[tot].size=1;
return tot;
}
void Update(int p){
a[p].size=a[a[p].l].size+a[a[p].r].size+a[p].cnt;
}
void Build(){ //为了保证-INF删不掉,且不影响删其他点,固定其为根节点
New(-INF);New(INF);
a[1].dat=0x7f7f7f7f;
a[1].r=2;
root=1;
Update(1);
}
void zig(int &p){
int q=a[p].l;
a[p].l=a[q].r;
a[q].r=p;
p=q; //这一步是为了让之前p的父节点连接到q上
Update(p);Update(a[p].r);
}
void zag(int &p){
int q=a[p].r;
a[p].r=a[q].l;
a[q].l=p;
p=q;
Update(p);Update(a[p].l);
}
void Insert(int &p,int val){
//printf("插入:p=%d\n val=%d\n",p,val);
if(p==0){
p=New(val);
return;
}
if(a[p].val==val){
a[p].cnt++;
Update(p);
return;
}
if(val<a[p].val){
Insert(a[p].l,val);
if(a[p].dat<a[a[p].l].dat) zig(p);
}
if(val>a[p].val){
Insert(a[p].r,val);
if(a[p].dat<a[a[p].r].dat) zag(p);
}
Update(p); //每次往上回溯前必须Update!
}
void Delete(int &p){ //一定没有左儿子
//printf("p=%d a[p].val=%d\n",p,a[p].val);
//printf("l=%d r=%d\n",a[p].l,a[p].r);
if(a[p].r){ //如果有右儿子
zag(p);
Delete(a[p].l);
Update(p);
}
else if(a[p].l==0&&a[p].r==0){ //已经是叶结点了
//printf("删除:a[p].cnt=%d\n",a[p].cnt);
p_d+=a[p].cnt; //计数器加上p的cnt
p=0; //删除掉这个结点
}
return;
}
void Clear(int &p,int val){ //去掉关键码≤val的所有结点
if(p==0) return;
if(val<a[p].val) {
Clear(a[p].l,val); //只进入左子树
Update(p);
}
else {
Clear(a[p].r,val);
Clear(a[p].l,val); //左右子树都进入
Update(p); //是否多余了?
}
//printf("Clear_val=%d\n",val);
if(a[p].val<=val&&p!=1) Delete(p); //回溯时,如果该节点符合条件,需要被删除
//注意到删除的时候,该结点的左子树一定被删完了,所以将其左旋一下就到叶节点了,就可以直接删除
}
int getval(int p,int x){ //返回在p的子树中排名为x的结点的值
//printf("Get_val:p=%d x=%d\n",p,x);
//printf("a[a[p].l].size=%d a[p].cnt=%d\n",a[a[p].l].size,a[p].cnt);
if(p==0) return -1;
if(a[a[p].l].size>=x) return getval(a[p].l,x);
else if(a[a[p].l].size<x&&a[a[p].l].size+a[p].cnt>=x) return a[p].val;
else return getval(a[p].r,x-a[a[p].l].size-a[p].cnt);
}
int main(){
//freopen("P1486_2.in","r",stdin);
//freopen("ans.txt","w",stdout);
Build();
scanf("%d%d",&n,&min);
for(int i=1;i<=n;i++){
//getchar();
//char x=getchar();int k;
char x;int k;
//scanf("%d",&k);
std::cin>>x>>k;
//printf("x=%c\n",x);
if(x=='I'){
//printf("插入:td=%d\n",td);
if(k<min) continue;
else {
Insert(root,k-td); //为了加入新员工时不受之前加减工资的影响,在插入时就直接带入原来的增加工资
p_i++;
}
}
else if(x=='A') td+=k;
else if(x=='S'){
td-=k;
Clear(root,min-td-1); //当前工资比min小的被清除
}
else if(x=='F') {
//printf("p_i=%d p_d=%d k=%d\n",p_i,p_d,k);
if(p_i+2-k-p_d<=1) std::cout<<-1<<std::endl;
else {
std::cout<<getval(root,p_i+2-k-p_d)+td<<std::endl;
}
}
}
//for(int p=1;p<=tot;p++) printf("p=%d val=%d cnt=%d size=%d l=%d r=%d\n",p,a[p].val,a[p].cnt,a[p].size,a[p].l,a[p].r);
std::cout<<p_d<<std::endl;
return 0;
}
自己写的Treap,提交只有30pts,但是下载数据在本地运行答案是正确的,求助大佬们