cf 1354D multiset(數值範圍1e6之間用線段樹實現multiset的插入,查找,單個刪除功能)

題目鏈接

線段樹最常見的每個節點是存未知的信息,但這題不一樣,建立線段樹的節點是保存數值的信息,這題每個節點記錄的是出現的次數
先通過原來"multiset"裏有的元素更新一下線段樹。
插入:插入num,把區間[num,num]的節點+1,然後pushUp。
查找: 查找第num大的數,看左子樹節點存的值是不是大於num,大於num的話就往左子樹找,否則num = num - 左子樹的值,然後往右子樹找,l == r時return l。
單個刪除:
查找到第k大的數num,然後對區間[num, num]的節點-1,然後pushUp。

#include <bits/stdc++.h>

using namespace std;

const int maxn = (int)1e6+100;
int n, q, tVal[maxn<<2], a[maxn];

void pushUp(int node) {
    tVal[node] = tVal[node<<1] + tVal[node<<1|1];
}
void build(int node, int l, int r) {
    if (l == r) {
        tVal[node] = 0;
        return;
    }
    int mid = (l + r) >> 1;
    build(node<<1, l, mid);
    build(node<<1|1, mid+1, r);
    pushUp(node);
}
void update(int node, int l, int r, int num, int val) {
    if (l == r) {
        tVal[node] += val;
        return;
    }
    int mid = (l + r) >> 1;
    if (num <= mid) update(node<<1, l, mid, num, val);
    else update(node<<1|1, mid+1, r, num, val);
    pushUp(node);
}
int query(int node, int l, int r, int num) {
    if (l == r) return l;
    int mid = (l + r) >> 1;
    if (tVal[node<<1] >= num) return query(node<<1, l, mid, num);
    else return query(node<<1|1, mid+1, r, num - tVal[node<<1]);
}
void solve(int node, int l, int r) {
    if (l == r) {
        cout << l << '\n';
        return;
    }
    int mid = (l + r) >> 1;
    if (tVal[node<<1]) solve(node<<1, l, mid);
    else solve(node<<1|1, mid+1, r);
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.precision(10);
    cout << fixed;
#ifdef LOCAL_DEFINE
    freopen("input.txt", "r", stdin);
#endif

    cin >> n >> q;
    build(1, 1, n);
    for (int i = 1; i <= n; ++i) {
        cin >> a[i];
        update(1, 1, n, a[i], 1);
    }
    for (int i = 0; i < q; ++i) {
        int k;
        cin >> k;
        if (k > 0) {
            update(1, 1, n, k, 1);
        } else {
            k = -k;
            int nu = query(1, 1, n, k);
            update(1, 1, n, nu, -1);
        }
    }
    if (!tVal[1]) cout << 0 << '\n';
    else solve(1, 1, n);

#ifdef LOCAL_DEFINE
    cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
#endif
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章