这道题建立权值线段树,可添加新点
题目链接:
分析: 建立权值线段树维护区间出现的数字个数cnt,lazy=1表示区间没有数。维护一个全局偏移量add
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 4e5 + 3;
const int base = 2e5 + 3;
struct T {
int l,r,cnt,lazy;
}t[maxn<<2];
void build(int p,int l,int r)
{
t[p].l=l,t[p].r=r,t[p].cnt=t[p].lazy=0;
if(l==r) return;
int mid=(l+r)>>1;
build(p*2,l,mid); build(p*2+1,mid+1,r);
}
void cal(int p)
{
if(!t[p].lazy) return;
t[p].lazy=t[p*2].cnt=t[p*2+1].cnt=0;
t[p*2].lazy=t[p*2+1].lazy=1;
}
void Insert(int p,int x)
{
if(t[p].l==t[p].r) {
if(t[p].l==x) t[p].cnt++;
return;
}
cal(p);
int mid=(t[p].l+t[p].r)>>1;
if(x<=mid) Insert(p*2,x);
else Insert(p*2+1,x);
t[p].cnt=t[p*2].cnt+t[p*2+1].cnt;
}
void update(int p,int x)
{
if(t[p].r<x) {
t[p].cnt=0,t[p].lazy=1; return;
}
if(t[p].l==t[p].r) {
if(t[p].r<x) t[p].cnt=0;
return;
}
int mid=(t[p].l+t[p].r)>>1;
cal(p);
update(p*2,x);
if(x>mid) update(p*2+1,x);
t[p].cnt=t[p*2].cnt+t[p*2+1].cnt;
}
int query(int p,int k)
{
if(t[p].l==t[p].r) return t[p].l;
cal(p);
if(k<=t[p*2+1].cnt) return query(p*2+1,k);
else return query(p*2,k-t[p*2+1].cnt);
}
int main()
{
int n,minv,num=0,k,add=0;
char op[2];
scanf("%d%d",&n,&minv);
build(1,0,maxn);
for(int i=1;i<=n;i++) {
scanf("%s%d",op,&k);
if(op[0]=='I') {
if(k<minv) continue;
num++;
Insert(1,k-add+base);
}
else if(op[0]=='A') add+=k;
else if(op[0]=='S') {
add-=k;
update(1,minv-add+base);
}
else {
if(k>t[1].cnt) printf("-1\n");
else printf("%d\n",query(1,k)+add-base);
}
}
printf("%d",num-t[1].cnt);
return 0;
} 
京公网安备 11010502036488号