用一个普通数组p[i]保存第i个人的生命值,一个树状数组c[h]表示生命值为h的人有多少个,h的范围为1--3*65535;
此时,query(x)表示生命值不多于x的人的个数,用二分来找生命值第k的的人,用一个数 tol 保存当前存活的人数。
代码:
#include <cstdio>
#include <cmath>
#include <climits>
#include <cstring>
#include <string>
#include <cctype>//tolower toupper isdigit isalpha islower isupper isspace
#include <algorithm>
#include <iostream>
#include <map>
#define LL long long
#define db double
#define pi acos(-1.0)
#define pr printf
#define sc scanf
#define mod
#define N 3*65535+5
using namespace std;
int c[N];
int p[30011];
int low(int i)
{
return i&(-i);
}
void add(int i,int x)
{
while(i<=N)
{
c[i]+=x;
i+=low(i);
}
}
int query(int i)
{
int r=0;
while(i)
{
r+=c[i];
i-=low(i);
}
return r;
}
int main()
{
int n,m,i,j,x,y,tol;
char s[10];
memset(c,0,sizeof(c));
while(sc("%d",&n)+1&&n)
{
tol=n;
for(i=0; i<n; ++i)
{
sc("%d",&x);
p[i+1] = x ;
add(x,1);
}
sc("%d",&m);
for(i=0; i<m; ++i)
{
sc("%s",s);
if(s[0]=='A')
{
sc("%d%d",&x,&y);
add(p[x],-1);
p[x]-=y;
if(p[x]>0)
add(p[x],1);
else
tol--;
}
else if(s[0]=='C')
{
sc("%d%d",&x,&y);
add(p[x],-1);
p[x]+=y;
add(p[x],1);
}
else
{
sc("%d",&x);
if(tol<x)
{
puts("-1");
continue;
}
int l=0,r=N-5,m;
while(l<=r)
{
m=(l+r)>>1;
if(x<=tol-query(m))
l=m+1;
else
r=m-1;
}
pr("%d\n",l);
}
}
pr("%d\n",tol);
}
return 0;
}