Treap板子

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

const int SIZE = 1e5 + 5;

class Treap {
    struct Node {
        int l, r;
        int val, dat; //节点的关键码,权值
        int cnt, size; //副本数,子树大小
    }a[SIZE];

public:
    int tot, root, INF = 0x7fffffff;

    Treap() {
        tot = 0;
        New(-INF), New(INF);
        root = 1, a[1].r = 2;
        Update(root);
    }

    int New(int val) {
        a[++tot].val = val;
        a[tot].r = a[tot].l = 0;
        a[tot].dat = rand();
        a[tot].cnt = a[tot].size = 1;
        return tot; 
    }

    void Update(int p) {
        a[p].size = a[a[p].l].size + a[a[p].r].size + a[p].cnt;
    }

    int GetRankByVal(int p, int val) {
        if (p == 0) return 0;
        
        if (val == a[p].val) return a[a[p].l].size + 1;
        if (val < a[p].val) return GetRankByVal(a[p].l, val);
        return GetRankByVal(a[p].r, val) + a[a[p].l].size + a[p].cnt;
    }

    int GetValByRank(int p, int rank) {
        if (p == 0) return INF;

        if (a[a[p].l].size >= rank) return GetValByRank(a[p].l, rank);
        if (a[a[p].l].size + a[p].cnt >= rank) return a[p].val;
        return GetValByRank(a[p].r, rank - a[a[p].l].size - a[p].cnt);
    }

    void zig(int &p) { //右旋
        int q = a[p].l;
        a[p].l = a[q].r, a[q].r = p, p = q;
        Update(a[p].r), Update(p);
    }

    void zag(int &p) { //左旋
        int q = a[p].r;
        a[p].r = a[q].l, a[q].l = p, p = q; 
        Update(a[p].l), Update(p);
    }

    void Insert(int &p, int val) {
        if (p == 0) {
            p = New(val);
            return;
        }

        if (val == a[p].val) {
            ++a[p].cnt, Update(p);
            return;
        }

        if (val < a[p].val) {
            Insert(a[p].l, val);
            if (a[p].dat < a[a[p].l].dat) zig(p);
        } else {
            Insert(a[p].r, val);
            if (a[p].dat < a[a[p].r].dat) zag(p);
        } 

        Update(p);
    }

    int GetPre(int val) {
        int ans = 1; // INF
        int p = root;

        while (p) {
            if(val == a[p].val) {
                if (a[p].l > 0) {
                    p = a[p].l;
                    while (a[p].r > 0) p = a[p].r;
                    ans = p;
                }
                break;
            } 

            if (a[p].val < val && a[p].val > a[ans].val) ans = p;

            p = a[p].val > val ? a[p].l : a[p].r;
        }

        return a[ans].val;
    }

    int GetNext(int val) {
        int ans = 2; //-INF
        int p = root;

        while (p) {
            if (a[p].val == val) {
                if (a[p].r > 0) {
                    p = a[p].r;
                    while (a[p].l > 0) p = a[p].l;
                    ans = p;
                }
                break;
            }

            if (a[p].val > val && a[p].val < a[ans].val) ans = p;
            
            p = a[p].val > val ? a[p].l : a[p].r;
        }

        return a[ans].val;
    }

    void Remove(int &p, int val) {
        if (p == 0) return;

        if (val == a[p].val) {
            if (a[p].cnt > 1) {
                --a[p].cnt, Update(p);
                return;
            }

            if (a[p].l || a[p].r) {
                if (a[p].r == 0 || a[a[p].l].dat > a[a[p].r].dat)
                    zig(p), Remove(a[p].r, val);
                else zag(p), Remove(a[p].l, val);
                
                Update(p);
            } 
            else p = 0;
            return;
        }

        val < a[p].val ? Remove(a[p].l, val) : Remove(a[p].r, val);
        Update(p);
    }
};

int n, _;

int main() {
    ios::sync_with_stdio(0); cin.tie(nullptr);

    Treap t = Treap();
    for (cin >> _; _; --_) {
        int opt, x; cin >> opt >> x;

        switch (opt)
        {
        case 1:
            t.Insert(t.root, x);
            break;
        case 2:
            t.Remove(t.root, x);
            break;
        case 3:
            cout << t.GetRankByVal(t.root, x) - 1 << endl;
            break;
        case 4:
            cout << t.GetValByRank(t.root, x + 1) << endl;
            break;
        case 5:
            cout << t.GetPre(x) << endl;
            break;
        case 6:
            cout << t.GetNext(x) << endl;
            break;
        default:
            break;
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/2aptx4869/p/13162372.html