一、题目
二、解法
这道题很新的一点就是加工资和减工资,这貌似要用到区间修改。
但是细细想想,操作的对象是全树,我们可以维护一个累积的修改值,新加入一个点的话要删去之前的累计的修改值,对于减工资的情况,判断有没有低于最低的限制。
注意如果一个一来人就低于最低线,那么这个人不被统计在最后的删除人数中。
#include <cstdio>
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
const int MAXN = 80005;
int read()
{
int x=0,flag=1;char c;
while((c=getchar())<'0' || c>'9') if(c=='-') flag=-1;
while(c>='0' && c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
return x*flag;
}
int n,m,ans,now,all,rt,Index;
int ch[MAXN][2],cnt[MAXN],siz[MAXN],val[MAXN],hp[MAXN];
void push_up(int x)
{
siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+cnt[x];
}
void rotate(int &x,int d)
{
int y=ch[x][d^1];
ch[x][d^1]=ch[y][d];
ch[y][d]=x;
push_up(x);
push_up(y);
x=y;
}
void ins(int &x,int v)
{
if(!x)
{
x=++Index;
cnt[x]=siz[x]=1;
ch[x][0]=ch[x][1]=0;
val[x]=v;hp[x]=rand();
return ;
}
if(v==val[x])
{
cnt[x]++;siz[x]++;
return ;
}
int d=v>val[x];
ins(ch[x][d],v);
if(hp[x]<hp[ch[x][d]])
rotate(x,d^1);
push_up(x);
}
void del(int &x,int v)
{
if(!x) return ;
if(v!=val[x])
del(ch[x][v>val[x]],v);
else
{
if(!ch[x][0] && !ch[x][1])
{
cnt[x]--;
siz[x]--;
if(cnt[x]==0)
x=0;
}
else if(ch[x][0] && !ch[x][1])
{
rotate(x,1);
del(ch[x][1],v);
}
else if(!ch[x][0] && ch[x][1])
{
rotate(x,0);
del(ch[x][0],v);
}
else
{
int d=hp[ch[x][0]]>hp[ch[x][1]];
rotate(x,d);
del(ch[x][d],v);
}
}
push_up(x);
}
int ask(int x,int v)
{
if(!x) return 0;
if(siz[ch[x][0]]>=v)
return ask(ch[x][0],v);
else if(siz[ch[x][0]]+cnt[x]<v)
return ask(ch[x][1],v-siz[ch[x][0]]-cnt[x]);
return val[x];
}
signed main()
{
srand(time(0));
n=read();m=read();
while(n--)
{
char c;int x;
scanf("%s",&c);x=read();
if(c=='I')
{
if(x<m) ;
else ins(rt,-x+now);//x-now
}
if(c=='A')
now+=x;
if(c=='S')
{
now-=x;
int t=-ask(rt,siz[rt]);
while(siz[rt] && m>t+now)
{
ans++;
del(rt,-t);
t=-ask(rt,siz[rt]);
}
}
if(c=='F')
{
if(siz[rt]<x)
{
puts("-1");
continue;
}
printf("%d\n",-ask(rt,x)+now);
}
}
printf("%d\n",ans);
}