题解:
比较裸的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; }