• [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;
            }
        }
    }
    
  • 相关阅读:
    查看git submodule更改
    /var/lib/docker空间占用过大迁移
    docker -修改容器
    docker重命名镜像repository和tag
    方法的重写、重载。
    方法的声明与使用。
    二维数组。
    标准输入输出流概述和输出语句。
    冒泡排序法。
    IO流,对象操作流优化。
  • 原文地址:https://www.cnblogs.com/mollnn/p/12531607.html
Copyright © 2020-2023  润新知