这道题建立权值线段树,可添加新点
题目链接:
分析: 建立权值线段树维护区间出现的数字个数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; }