替罪羊树

后言

  • 一定要值相同的放一起统计啊,不然删除会很难受的。
  • 向这种重量平衡树,可以解决 double 除 2 丧失精度的一些问题吧。

参考实现

#include <vector>
#include <iostream>
using namespace std;
const double alpha = 0.7;
const int M = 100100;
struct node
{
    node* ls, * rs;
    int s, v, c, sz;// sum val cnt size
    void up()
    {
        s = ls->s + rs->s + c;
        sz = ls->sz + rs->sz + 1;
    }
    bool bad()
    {
        return max(ls->sz, rs->sz) >= alpha * sz;
    }
};
node a[M]; int idx = 0;
node* newnode() { idx++; return &a[idx]; }
node* null;
void fd(node* x, vector<node*>& v)
{
    if (x == null)return;
    fd(x->ls, v);
    if (x->c)v.push_back(x);
    fd(x->rs, v);
}
node* bud(int l, int r, vector<node*>& v)
{
    if (r < l)return null;
    const int m = l + r >> 1;
    auto x = v[m];
    x->ls = bud(l, m - 1, v);
    x->rs = bud(m + 1, r, v);
    x->up(); return x;
}
void rebud(node*& x)
{
    vector<node*> v; fd(x, v); x = bud(0, v.size() - 1, v);
}
void add(node*& x, int v)
{
    if (x == null)
    {
        x = newnode();
        x->ls = x->rs = null;
        x->s = x->c = x->sz = 1;
        x->v = v;
    }
    else
    {
        if (v < x->v)add(x->ls, v);
        else if (v > x->v)add(x->rs, v);
        else x->c++; x->up(); if (x->bad())rebud(x);
    }
}
void del(node*& x, int v)
{
    if (v < x->v)del(x->ls, v);
    else if (v > x->v)del(x->rs, v);
    else x->c--; x->up(); if (x->bad())rebud(x);
}
int rk(node* x, int v)
{
    if (x == null)return 1;
    if (v < x->v)return rk(x->ls, v);
    const int le = x->ls->s + x->c;
    if (v > x->v)return le + rk(x->rs, v);
    return x->ls->s + 1;
}
int kth(node* x, int p)
{
    if (p <= x->ls->s)return kth(x->ls, p);
    const int le = x->ls->s + x->c;
    if (p <= le)return x->v;
    return kth(x->rs, p - le);
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr); cout.tie(nullptr);
    null = newnode();
    null->ls = null->rs = null;
    auto rt = null;
    int n; cin >> n;
    for (int i = 1; i <= n; i++)
    {
        int op, x; cin >> op >> x;
        if (op == 1)add(rt, x);
        if (op == 2)del(rt, x);
        if (op == 3)cout << rk(rt, x) << '\n';
        if (op == 4)cout << kth(rt, x) << '\n';
        if (op == 5)cout << kth(rt, rk(rt, x) - 1) << '\n';
        if (op == 6)cout << kth(rt, rk(rt, x + 1)) << '\n';
    }
    return 0;
}
posted @ 2025-04-23 08:01  LUHCUH  阅读(9)  评论(0)    收藏  举报