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;
}
View Code

 

posted @ 2020-05-24 20:17  starve_to_death  阅读(238)  评论(0编辑  收藏  举报