这题方法应该有很多,什么树状数组线段树都能搞。。
用splay的话就是维护工资序列咯,但是每次修改都逐个修改的话肯定会T掉,注意到修改是整体修改,所以只要维护一个相对的修改值,然后修改的时候要考虑上这个相对值。。增加工资显然不会使员工离开,所以只要在减少工资的时候check一下就好了。。删除的时候要注意维护size。。
#include<iostream>
#include<cstdio>
#include<memory.h>
using namespace std;
const int inf=999999999,maxn=100005;
int n,minp,i,ans=0,del=0,k,root=0,nnode=0,c[maxn][2],pre[maxn],size[maxn],same[maxn],data[maxn];
char cc;
void update(int x){size[x]=size[c[x][0]]+size[c[x][1]]+same[x];}
void newnode(int &x,int fa,int num)
{
x=++nnode;
pre[x]=fa;data[x]=num;
size[x]=same[x]=1;
c[x][0]=c[x][1]=0;
}
void rot(int x,int kind)
{
int y=pre[x];int z=pre[y];
c[y][!kind]=c[x][kind];pre[c[x][kind]]=y;
c[x][kind]=y;pre[y]=x;
pre[x]=z;
if (z) c[z][c[z][1]==y]=x;
update(y);update(x);if (z) update(z);
}
void splay(int x,int goal)
{
int y,z,kind;
while (pre[x]!=goal)
{
if (pre[pre[x]]==goal) rot(x,c[pre[x]][0]==x);
else
{
y=pre[x];z=pre[y];kind=c[z][0]==y;
if (c[y][!kind]==x) rot(y,kind);else rot(x,!kind);
rot(x,kind);
}
}
if (goal==0) root=x;
}
void insert(int k)
{
int get=root;
if (!root) newnode(root,0,k);
else
{
if (data[get]==k) same[get]++,size[get]++;
else
{
while (c[get][data[get]<k])
{
get=c[get][data[get]<k];
if (data[get]==k)
{
same[get]++,splay(get,0);
return;
}
}
newnode(c[get][data[get]<k],get,k);
splay(c[get][data[get]<k],0);
}
}
}
int findkth(int x,int k)
{
if (size[c[x][0]]>=k) return findkth(c[x][0],k);
else if (size[c[x][0]]+same[x]>=k) return data[x];
else return findkth(c[x][1],k-size[c[x][0]]-same[x]);
}
void check(int x)
{
if (!x) return;
if (data[x]+del<minp)
{
ans+=size[c[x][0]]+same[x];
pre[c[x][1]]=pre[x];c[pre[x]][c[pre[x]][1]==x]=c[x][1];
if (pre[x]==0) root=c[x][1];
int t=pre[x];
while (t)
{
update(t);
t=pre[t];
}
check(c[x][1]);
}
else check(c[x][0]);
}
void print(int x)
{
printf("xu:%d num:%d lc:%d rc:%d size:%d same:%d\n",x,data[x],c[x][0],c[x][1],size[x],same[x]);
if (c[x][0]) print(c[x][0]);if (c[x][1]) print(c[x][1]);
}
int main()
{
freopen("cny.in","r",stdin);
scanf("%d%d ",&n,&minp);
size[0]=same[0]=data[0]=pre[0]=0;
for (i=1;i<=n;i++)
{
scanf("%c%d ",&cc,&k);
if (cc=='I'&&k>=minp) insert(k-del);
if (cc=='A') del+=k;
if (cc=='S') del-=k,check(root);
if (cc=='F') if (size[root]>=k) printf("%d\n",findkth(root,size[root]+1-k)+del); else printf("-1\n");
}
printf("%d",ans);
}