D. Multiset(带排名的数组数组)
题:https://codeforces.com/contest/1354/problem/D
题意:有个multiset,开始有n个数,有俩种操作,1、加入ki。2、删除集合中第k小的,问最后若这个集合大小不为0输出任意一个数,否则输出0;
分析:由于内存要求,不可用splay之类的数据结构,也有点大材小用,那么考虑用树状数组处理,这里有个排名的问题,要是我们知道排名的数是哪个就基本能用树状数组解决,下面是用前缀和的树状数组来得到排名k的数。
#include <bits/stdc++.h> using namespace std; typedef long long ll; #define pb push_back const int inf =0x3f3f3f3f; const int M=(1<<20); const int N=(M)+6; const double PI=3.1415926535; int tr[N]; struct bit{ void add(int x,int c){ for(int i=x;i<N;i+=i&(-i)) tr[i]+=c; } int kth(int k){ int res=0; for(int i=(M>>1);i;i>>=1){ if(tr[res+i]<k){ k-=tr[res+i]; res+=i; } } return res+1; } }BIT; int main(){ int n,q; scanf("%d%d",&n,&q); for(int x,i=1;i<=n;i++){ scanf("%d",&x); BIT.add(x,1); } while(q--){ int k; scanf("%d",&k); if(k>0){ BIT.add(k,1); } else{ int tmp=BIT.kth(-k); ///cout<<tmp<<endl; BIT.add(tmp,-1); } } int ans=BIT.kth(1); if(ans>=M){ printf("0"); } else printf("%d",ans); return 0; }