题意:手动实现一个Mutilset,输入n个数,每个数都属于(1-n),然后给出m个操作,删除第X小的数,或者增加一个数(1-n),最后输出Multiset为空,或者随便输出一个Multiset中的值
解法:树状数组+二分查找,因为本题对内存要求严格,所以不能直接用Multiset(他具体占多少空间,我也不知道,但是应该比数组大),
需要注意,每个数字都是1-n的,所以可以用桶计数,就是开个数组num,插入x就让num[x]+1,删除的时候用二分求前缀和,找到第X个数,动态求前缀和用树状数组解决
代码:
#include<bits/stdc++.h> using namespace std; const int maxn=1000010; const int INF=2000000010; typedef long long ll; int n, m, p; int num[maxn]; void add(int x, int cnt) { for(int i=x; i<=n; i+=(i&-i)) { num[i]+=cnt; } } int get_sum(int x) { int ans=0; for(int i=x; i>=1; i-=(i&-i)) { ans+=num[i]; } return ans; } void del(int x) { int L = 1, R = n, ans = 1; while(L <= R) { int mid=(L+R)/2; if(get_sum(mid)<x) L=mid+1; else R=mid-1, ans=mid; } add(ans, -1); } int main() { scanf("%d%d", &n, &m); for(int i=1; i<=n; i++) { scanf("%d", &p); add(p, 1); } for(int i=1; i<=m; i++) { scanf("%d", &p); if(p>0) add(p, 1); else del(abs(p)); } if(get_sum(n)==0) puts("0"); else { int ans = n; for(int i=1; i<=n; i++) { if(get_sum(i)>0) { ans = i; break; } } printf("%d\n", ans); } return 0; }