前期知识:
权值线段树本质 —— 每个节点存取的是一个区间内的信息,即在 [l,r] 这个区间内的信息,而普通的线段树可能是维护区间内的最大值,sum和之类的信息。
当数据范围比较大,但是数据个数不多的时候,可以使用离散化实现权值线段树。
权值线段树可用于求取全局第 k 大之类的信息。
题意:
建立员工档案,要求支持动态加入、删除员工,统计工资第 k 大的员工,员工工资最多100000。
思路:
建立权值线段树,统计每一个区间内的人数,记一个add变量,用来记录现在对工资的加减总和,然后用权值线段树即可动态删点、插点、统计区间第 K 大。
在删点的时候,可以用lazy进行标记,标记一段区间num为0,对时间进行优化(不优化也能过),详见代码。
代码:
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#define rep(i,a,b) for(int i = a; i <= b; i++)
using namespace std;
const int N = 401000;
const int base = 200020;
struct Tree{
int l,r,num,lazy;
}t[N*4];
char s[10];
int minn,add;
void build(int p,int l,int r)
{
t[p].l = l, t[p].r = r, t[p].num = 0, t[p].lazy = 0;
if(t[p].l == t[p].r) return;
int mid = (l+r) >> 1;
build(p*2,l,mid);
build(p*2+1,mid+1,r);
}
void calc(int p)
{
if(t[p].lazy == 0) return;
else{
t[p].lazy = 0;
t[p*2].lazy = 1, t[p*2+1].lazy = 1;
t[p*2].num = t[p*2+1].num = 0;
}
}
void insert(int p,int x)
{
if(t[p].l == t[p].r){
if(t[p].l == x)
t[p].num++;
return;
}
int mid = (t[p].l+t[p].r)>>1;
calc(p);
if(x <= mid) insert(p*2,x);
else insert(p*2+1,x);
t[p].num = t[p*2].num+t[p*2+1].num;
}
void update(int p,int x)
{
if(t[p].r < x){
t[p].num = 0, t[p].lazy = 1;
return;
}
if(t[p].l == t[p].r){
if(t[p].r < x) t[p].num = 0;//n-=t[p].num, t[p].num = 0;
return;
}
int mid = (t[p].l+t[p].r)>>1;
calc(p);
if(x <= mid) update(p*2,x);
else{
update(p*2,x);
update(p*2+1,x);
}
t[p].num = t[p*2].num + t[p*2+1].num;
}
int ask(int p,int x)
{
if(t[p].l == t[p].r) return t[p].l;
int mid = (t[p].l + t[p].r)>>1;
calc(p);
if(t[p*2].num >= x) return ask(p*2,x);
else return ask(p*2+1,x-t[p*2].num);
}
int main()
{
int kk,x,sum = 0;
scanf("%d%d",&kk,&minn);
build(1,0,400100);
rep(i,1,kk)
{
// printf("n:%d,add:%d\n",t[1].num,add);
scanf("%s%d",s,&x);
if(s[0] == 'I')
{
if(x < minn) continue;
sum++;
insert(1,x-add+base);
}
else if(s[0] == 'A')
add += x;
else if(s[0] == 'S')
{
add -= x;
update(1,minn-add+base);
}
else{
if(x > t[1].num) printf("-1\n");
else printf("%d\n",ask(1,t[1].num-x+1)+add-base);
}
}
printf("%d\n",sum-t[1].num);
return 0;
}
/*
18 9
A 671
S 211
S 492
A 560
I 446
I 116
I 945
I 441
A 59
S 315
I 58
S 839
A 873
F 725
A 109
I 521
F 998
A 938
*/