codeforces 1354 D. Multiset

题意:手动实现一个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;
}

猜你喜欢

转载自www.cnblogs.com/ertuan/p/12927845.html