Educational Codeforces Round 87 (Rated for Div. 2) D

D - Multiset

题目大意:给一个长度为n的数组a,有q次操作,每次输入一个数k,如果k是正数则插入a数组中,负数就删除 下标为-k的数,下标从1-n;

思路:用树状数组维护每个数前面有几个数,即是第几大,插入一个数add操作,删除用二分查找,找到那个数。

code

#include <iostream>
#include <string>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <queue>
#include <functional>
#include <map>
#include <set>
#include <stack>
#include <vector>
#define FT(a, b) memset(a, b, sizeof(a))
#define FAT(a) memset(a, 0, sizeof(a))
using namespace std;
typedef long long ll;
const int M = 1e6 + 100;
const int INF = 0x3f3f3f3f;
const int mod = 998244353;
const double PI = 3.1415926535;
int c[M], n, q;
int lowbit(int x) { return x & -x; }

void add(int x, int y)
{
    for (int i = x; i <= n; i += lowbit(i))
        c[i] += y;
}
ll sum(int x)
{
    ll ans = 0;
    for (int i = x; i > 0; i -= lowbit(i))
        ans += c[i];
    return ans;
}
int find(int x)
{
    int l = 1, r = n;
    while (l < r)
    {
        int mid = l + r >> 1;
        if (sum(mid) >= x)
            r = mid;
        else
            l = mid + 1;
    }
    return l;
}
int main()
{
#ifdef ONLINE_JUDGE
#else
    freopen("D:\\code\\c++\\in.txt", "r", stdin);
#endif
    scanf("%d%d", &n, &q);
    FAT(c);
    for (int i = 1; i <= n; i++)
    {
        int a;
        scanf("%d", &a);
        add(a, 1);
    }
    while (q--)
    {
        int x;
        scanf("%d", &x);
        if (x < 0)
            add(find(-x), -1);
        else
            add(x, 1);
    }
    int x = find(1);
    if (c[x])
        printf("%d\n", x);
    else
        puts("0");
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/ignorance/p/12918366.html