题解:
比较裸的Splay;
整体修改工资用一个变量Tag维护,相当于Splay里的节点都加上Tag
删除的时候用一个点把走不走的员工给隔开,然后删除一整颗子树
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=500009;
int T,lim;
int ans;
int nn,root;
int tag;
int fa[maxn],ch[maxn][2],siz[maxn],cnt[maxn],ky[maxn];
int Splayinit(){
ans=root=nn=tag=0;
fa[0]=ch[0][0]=ch[0][1]=siz[0]=cnt[0]=ky[0]=0;
}
inline int son(int x){
return ch[fa[x]][1]==x;
}
inline int pushup(int x){
siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+cnt[x];
}
int Rotate(int x){
int y=fa[x];
int z=fa[y];
int b=son(x),c=son(y);
int a=ch[x][b^1];
if(z)ch[z][c]=x;
else root=x;
fa[x]=z;
if(a)fa[a]=y;
ch[y][b]=a;
fa[y]=x;ch[x][b^1]=y;
pushup(y);pushup(x);
}
int Splay(int x,int i){
while(fa[x]!=i){
int y=fa[x];
int z=fa[y];
if(z==i){
Rotate(x);
}else{
if(son(x)==son(y)){
Rotate(y);Rotate(x);
}else{
Rotate(x);Rotate(x);
}
}
}
}
int Ins(int val){
int x=root,y=0;
while(x){
y=x;
if(ky[x]==val){
++cnt[x];++siz[x];Splay(x,0);
return 0;
}
if(val>ky[x])x=ch[x][1];
else x=ch[x][0];
}
x=++nn;
fa[x]=y;ch[x][0]=ch[x][1]=0;
siz[x]=cnt[x]=1;ky[x]=val;
if(!y){
root=x;
}else{
if(val>ky[y])ch[y][1]=x;
else ch[y][0]=x;
}
Splay(x,0);
}
int Del(){
Ins(lim-tag-1);
ans=ans+siz[ch[root][0]]+cnt[root]-1;
root=ch[root][1];
fa[root]=0;
}
int Kth(int k){
int x=root;
for(int l;x;){
l=ch[x][0];
if(k<=siz[l]){
x=ch[x][0];
}else if(k>siz[l]+cnt[x]){
k-=(siz[l]+cnt[x]);
x=ch[x][1];
}else{
return ky[x];
}
}
}
int main(){
scanf("%d%d",&T,&lim);
Splayinit();
while(T--){
char opty=getchar();
while((opty<‘A‘)||(opty>‘Z‘))opty=getchar();
int x;
scanf("%d",&x);
if(opty==‘I‘){
if(x<lim)continue;
Ins(x-tag);
}
if(opty==‘A‘){
tag+=x;
}
if(opty==‘S‘){
tag-=x;
Del();
}
if(opty==‘F‘){
if(x>siz[root]){
printf("-1\n");
}else{
x=siz[root]-x+1;
printf("%d\n",Kth(x)+tag);
}
}
}
printf("%d\n",ans);
return 0;
}