CF1354D MultiSet(树状数组+二分)

题意:

有两种操作:一种是把一个元素加入到集合中,一种是删除集合中第k个元素,求解最后集合里的元素。

题解:

祖传的树状数组套二分,这种题可遇不可求,比赛时直接秒了,不太会出现这么裸的数据结构题了,,,

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+500;
int n,q;
int lowbit (int x) {
    return x&-x;
}
int a[maxn];
int c[maxn];
void update (int x,int val) {
    for (int i=x;i<maxn;i+=lowbit(i)) c[i]+=val;
 
}
int sum (int x) {
    int ans=0;
    for (int i=x;i;i-=lowbit(i))
        ans+=c[i];
    return ans;
}
int kth (int x,int k) {
    int l=x+1,r=maxn;
    int ans=-1;
    while (l<=r) {
        int mid=(l+r)>>1;
        if (sum(mid)-sum(x)>=k) r=mid-1,ans=mid;
        else l=mid+1;
    }
    return ans;
}
int main () {
    scanf("%d%d",&n,&q);
    for (int i=1;i<=n;i++) {
        scanf("%d",&a[i]);
        a[i]+=100;
        update(a[i],1);
    }
    for (int i=1;i<=q;i++) {
        int x;
        scanf("%d",&x);
        if (x<=0) {
            x=-x;
            int tt=kth(1,x);
            if (tt==-1) continue;
            update(tt,-1);
        }
        else {
            update(x+100,1);
        }
    }
    int f=0;
    for (int i=1;i<=n;i++) {
        if (sum(i+100)-sum(i+99)) {
            printf("%d\n",i);
            f=1;
            break;
        }
    }
    if (!f) {
        printf("0\n");
    }
}

 

posted @ 2020-05-19 16:52  zlc0405  阅读(240)  评论(0编辑  收藏  举报