替罪羊树

2024-08-12

替罪羊树通过计算不平衡率、拍平重建操作,维护树的平衡,实现数据的高效插入、删除

#include <bits/stdc++.h>
#define io cin.tie(0), cout.tie(0), ios::sync_with_stdio(false)
#define LL long long
#define ULL unsigned long long
#define EPS 1e-8
#define INF 0x7fffffff
#define SUB -INF - 1
using namespace std;
const int N = 100010;
const double alpha = 0.75;
struct node
{
    int rs, ls;
    int val;
    int tot;
    int size;
    int del;
} t[N];
int order[N], cnt;
int tree_stack[N], top = 0;
int root = 0;
void inorder(int u)
{
    if (!u)
        return;
    inorder(t[u].ls);
    if (t[u].del)
        order[++cnt] = u;
    else
        tree_stack[++top] = u;
    inorder(t[u].rs);
}
void Initnode(int u)
{
    t[u].ls = t[u].rs = 0;
    t[u].size = t[u].tot = t[u].del = 1;
}
void update(int u)
{
    t[u].size = t[t[u].ls].size + t[t[u].rs].size + 1;
    t[u].tot = t[t[u].ls].tot + t[t[u].rs].tot + 1;
}
void build(int l, int r, int &u)
{
    int mid = (l + r) >> 1;
    u = order[mid];
    if (l == r)
    {
        Initnode(u);
        return;
    }
    if (l < mid)
        build(l, mid - 1, t[u].ls);
    if (l == mid)
        t[u].ls = 0;
    build(mid + 1, r, t[u].rs);
    update(u);
}
void rebuild(int &u)
{
    cnt = 0;
    inorder(u);
    if (cnt)
        build(1, cnt, u);
    else
        u = 0;
}
bool notbalance(int u)
{
    if ((double)t[u].size * alpha <= (double)max(t[t[u].ls].size, t[t[u].rs].size))
        return true;
    return false;
}
void Insert(int &u, int x)
{
    if (!u)
    {
        u = tree_stack[top--];
        t[u].val = x;
        Initnode(u);
        return;
    }
    t[u].size++;
    t[u].tot++;
    if (t[u].val >= x)
        Insert(t[u].ls, x);
    else
        Insert(t[u].rs, x);
    if (notbalance(u))
        rebuild(u);
}
int Rank(int u, int x)
{
    if (u == 0)
        return 0;
    if (x > t[u].val)
        return t[t[u].ls].size + t[u].del + Rank(t[u].rs, x);
    return Rank(t[u].ls, x);
}
int kth(int k)
{
    int u = root;
    while (u)
    {
        if (t[u].del && t[t[u].ls].size + 1 == k)
            return t[u].val;
        else if (t[t[u].ls].size >= k)
            u = t[u].ls;
        else
        {
            k -= t[t[u].ls].size + t[u].del;
            u = t[u].rs;
        }
    }
    return t[u].val;
}
void Del_k(int &u, int k)
{
    t[u].size--;
    if (t[u].del && t[t[u].ls].size + 1 == k)
    {
        t[u].del = 0;
        return;
    }
    if (t[t[u].ls].size + t[u].del >= k)
        Del_k(t[u].ls, k);
    else
        Del_k(t[u].rs, k - t[t[u].ls].size - t[u].del);
}
void Del(int x)
{
    Del_k(root, Rank(root, x) + 1);
    if (t[root].tot * alpha >= t[root].size)
        rebuild(root);
}
int main()
{
    for (int i = N - 1; i >= 1; i--)
        tree_stack[++top] = i;
    int q;
    cin >> q;
    while (q--)
    {
        int opt, x;
        cin >> opt >> x;
        switch (opt)
        {
        case 1:
            Insert(root, x);
            break;
        case 2:
            Del(x);
            break;
        case 3:
            printf("%d\n", Rank(root, x) + 1);
            break;
        case 4:
            printf("%d\n", kth(x));
            break;
        case 5:
            printf("%d\n", kth(Rank(root, x)));
            break;
        case 6:
            printf("%d\n", kth(Rank(root, x + 1) + 1));
            break;
        }
    }
    return 0;
}