后言
- 一定要值相同的放一起统计啊,不然删除会很难受的。
- 向这种重量平衡树,可以解决 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;
}