739 words
4 minutes
Template of FHQ-Treap

written by ChatGPT.

#include <iostream>
#include <memory>
#include <vector>
#include <array>
#include <cstdint>
template <typename Tp>
using OwnPtr = std::unique_ptr<Tp>;
template <typename Tp>
using RefPtr = Tp*;
class FhqTreap {
private:
struct Node {
std::array<RefPtr<Node>, 2> son{nullptr, nullptr};
int cnt = 0, val = 0, sz = 0;
std::uint32_t pri = 0;
};
std::vector<OwnPtr<Node>> pool;
std::uint32_t seed = 114514;
auto rnd() -> std::uint32_t {
seed ^= seed << 13;
seed ^= seed >> 17;
seed ^= seed << 5;
return seed;
}
auto size(RefPtr<Node> x) -> int {
return x ? x->sz : 0;
}
void pushUp(RefPtr<Node> x) {
if (!x) return;
x->sz = x->cnt + size(x->son[0]) + size(x->son[1]);
}
auto newNode(int v) -> RefPtr<Node> {
pool.push_back(std::make_unique<Node>());
auto p = pool.back().get();
p->val = v;
p->cnt = p->sz = 1;
p->pri = rnd();
return p;
}
/*
equal == false:
x: val < v
y: val >= v
equal == true:
x: val <= v
y: val > v
*/
void split(
RefPtr<Node> p,
int v,
RefPtr<Node>& x,
RefPtr<Node>& y,
bool equal = false
) {
if (!p) {
x = y = nullptr;
return;
}
if (p->val < v || (equal && p->val == v)) {
x = p;
split(p->son[1], v, x->son[1], y, equal);
pushUp(x);
} else {
y = p;
split(p->son[0], v, x, y->son[0], equal);
pushUp(y);
}
}
auto merge(RefPtr<Node> x, RefPtr<Node> y) -> RefPtr<Node> {
if (!x || !y) {
return x ? x : y;
}
if (x->pri < y->pri) {
x->son[1] = merge(x->son[1], y);
pushUp(x);
return x;
} else {
y->son[0] = merge(x, y->son[0]);
pushUp(y);
return y;
}
}
auto kth(RefPtr<Node> x, int k) -> RefPtr<Node> {
while (x) {
int ls = size(x->son[0]);
if (k <= ls) {
x = x->son[0];
} else if (k <= ls + x->cnt) {
return x;
} else {
k -= ls + x->cnt;
x = x->son[1];
}
}
return nullptr;
}
auto rightMost(RefPtr<Node> x) -> RefPtr<Node> {
if (!x) return nullptr;
while (x->son[1]) x = x->son[1];
return x;
}
auto leftMost(RefPtr<Node> x) -> RefPtr<Node> {
if (!x) return nullptr;
while (x->son[0]) x = x->son[0];
return x;
}
public:
RefPtr<Node> rt = nullptr;
FhqTreap() = default;
~FhqTreap() {
clear();
}
void clear() {
rt = nullptr;
std::vector<OwnPtr<Node>>().swap(pool);
seed = 114514;
}
void insert(int v) {
RefPtr<Node> a = nullptr;
RefPtr<Node> b = nullptr;
RefPtr<Node> c = nullptr;
split(rt, v, a, b, false); // a < v, b >= v
split(b, v, c, b, true); // c == v, b > v
if (c) {
c->cnt++;
pushUp(c);
} else {
c = newNode(v);
}
rt = merge(merge(a, c), b);
}
bool remove(int v) {
RefPtr<Node> a = nullptr;
RefPtr<Node> b = nullptr;
RefPtr<Node> c = nullptr;
split(rt, v, a, b, false); // a < v, b >= v
split(b, v, c, b, true); // c == v, b > v
if (!c) {
rt = merge(a, b);
return false;
}
if (c->cnt > 1) {
c->cnt--;
pushUp(c);
} else {
auto del = c;
c = merge(c->son[0], c->son[1]);
del->son[0] = del->son[1] = nullptr;
del->cnt = del->sz = 0;
}
rt = merge(merge(a, c), b);
return true;
}
int find_rank(int v) {
RefPtr<Node> a = nullptr;
RefPtr<Node> b = nullptr;
split(rt, v, a, b, false); // a < v, b >= v
int ans = size(a) + 1;
rt = merge(a, b);
return ans;
}
int find_kth(int k) {
if (!rt || k <= 0 || k > rt->sz) return -1;
auto x = kth(rt, k);
return x ? x->val : -1;
}
int find_prev(int v) {
RefPtr<Node> a = nullptr;
RefPtr<Node> b = nullptr;
split(rt, v, a, b, false); // a < v, b >= v
auto x = rightMost(a);
int ans = x ? x->val : -1;
rt = merge(a, b);
return ans;
}
int find_next(int v) {
RefPtr<Node> a = nullptr;
RefPtr<Node> b = nullptr;
split(rt, v, a, b, true); // a <= v, b > v
auto x = leftMost(b);
int ans = x ? x->val : -1;
rt = merge(a, b);
return ans;
}
};
auto main() -> int {
int T;
std::cin >> T;
FhqTreap treap;
while (T--) {
int op, x;
std::cin >> op >> x;
switch (op) {
case 1:
treap.insert(x);
break;
case 2:
treap.remove(x);
break;
case 3:
std::cout << treap.find_rank(x) << '\n';
break;
case 4:
std::cout << treap.find_kth(x) << '\n';
break;
case 5:
std::cout << treap.find_prev(x) << '\n';
break;
case 6:
std::cout << treap.find_next(x) << '\n';
break;
}
}
return 0;
}
Template of FHQ-Treap
https://blog.517group.cn/posts/202605192119/
Author
XianRuiDendro
Published at
2026-05-19
License
CC BY-NC-SA 4.0