[LOJ107] 维护全序集

对于 2,3 操作,用权值线段树处理

对于 4,5 操作,用 std::multiset 处理

注意 s.upper_boundupper_bound 的区别,后者复杂度爆炸

#include <bits/stdc++.h>
using namespace std;

#define int long long
const int N = 1000005;
const int M = 10000005;

int a[M], ch[M][2], t1, t2, t3, n = 1e9 + 1, m, ind = 1;

void modify(int p, int l, int r, int pos, int key) {
    a[p] += key;
    if (l < r) {
        if (pos <= (l + r) / 2) {
            if (ch[p][0] == 0)
                ch[p][0] = ++ind;
            modify(ch[p][0], l, (l + r) / 2, pos, key);
        } else {
            if (ch[p][1] == 0)
                ch[p][1] = ++ind;
            modify(ch[p][1], (l + r) / 2 + 1, r, pos, key);
        }
    }
}

int query(int p, int l, int r, int ql, int qr) {
    if (l > qr || r < ql || p == 0)
        return 0;
    if (l >= ql && r <= qr)
        return a[p];
    return query(ch[p][0], l, (l + r) / 2, ql, qr) + query(ch[p][1], (l + r) / 2 + 1, r, ql, qr);
}

int kth(int p, int l, int r, int k) {
    if (a[p] < k)
        return 0;
    if (l == r)
        return l;
    if (a[ch[p][0]] < k)
        return kth(ch[p][1], (l + r) / 2 + 1, r, k - a[ch[p][0]]);
    return kth(ch[p][0], l, (l + r) / 2, k);
}

int find(int x) {
    int p = 1;
    int l = 1, r = n;
    while (p && l < r) {
        if (x <= (l + r) / 2)
            r = (l + r) / 2, p = ch[p][0];
        else
            l = (l + r) / 2 + 1, p = ch[p][1];
    }
    return p;
}

void insert(int x) { modify(1, 1, n, x, 1); }

void remove(int x) { modify(1, 1, n, x, -1); }

int kth(int k) { return kth(1, 1, n, k); }

int getrank(int x) { return query(1, 1, n, 1, x - 1); }

multiset<int> s, u;

signed main() {
    ios::sync_with_stdio(false);
    scanf("%lld", &m);
    while (m--) {
        scanf("%lld%lld", &t1, &t2);
        switch (t1) {
            case 0:
                insert(t2 + 1);
                s.insert(t2);
                u.insert(-t2);
                break;
            case 1:
                remove(t2 + 1);
                s.erase(s.find(t2));
                u.erase(u.find(-t2));
                break;
            case 2:
                printf("%lld
", kth(t2) - 1);
                break;
            case 3:
                printf("%lld
", getrank(t2 + 1));
                break;
            case 4: {
                auto tmp1 = u.upper_bound(-t2);
                if (tmp1 == u.end())
                    puts("-1");
                else
                    printf("%lld
", -*tmp1);
            } break;
            case 5: {
                auto tmp2 = s.upper_bound(t2);
                if (tmp2 == s.end())
                    puts("-1");
                else
                    printf("%lld
", *tmp2);
            } break;
        }
    }
}
原文地址:https://www.cnblogs.com/mollnn/p/12531607.html