FHQ 入土教程
应 Vector_S 要求。
如果觉得文章中的马蜂过于毒瘤,可以翻到最后看格式化过的。
前置知识:堆,BST。
FHQ Treap 是什么?
一种依靠 split 和 merge 保持平衡的平衡树。
广泛应用于序列维护问题。
结构体定义
考虑每个点需要维护什么。
这里规定
一般平衡树题要维护排名信息,所以要维护每个点的子树大小
还要有一个
这里的信息比较简单,只需要更新
struct T
{
T *l, *r;int v, k, s;
T(int _v) : l(0), r(0), v(_v), k(rand()), s(1) {}
void p() {s = 1;if(l) s += l -> s;if(r) s += r -> s;}
}*r; //根
Split(x,k,a,b)
分为两种:按权值分裂和按大小分裂。
按权值分裂
将
为空树:a = b = 0;
:b = x, Split(x->l, k, a, b->l), b->p();
如果
于是在
没人要的
:a = x, Split(x->r, k, a->r, b), a->p();
同理,如果
于是在
void S(T *x, int k, T *&a, T *&b)
{
if(!x) {a = b = 0;return;}
if(x->v > k) b = x, S(x->l, k, a, b->l), b->p();
else a = x, S(x->r, k, a->r, b), a->p();
}
按大小分裂
先咕着。
Merge(a,b)
合并
这里规定
为空树返回 , 为空树返回 。 :将 的右子树与 合并。 :将 与 的左子树合并。
这个比较好理解吧。
T *M(T *a, T *b)
{
if(!a) return b;if(!b) return a;
if(a->k < b->k) {a->r = M(a->r, b);a->p();return a;}
else {b->l = M(a, b->l);b->p();return b;}
}
插入 v
分裂出权值
之后将
void I(int v) {T *a, *b;S(r, v, a, b);r = M(a, M(new T(v), b));}
删除 v
先分裂出权值
再把
之后删掉一个
最后把
void D(int v) {T *a, *b, *c;S(r, v, a, c);S(a, v - 1, a, b);r = M(a, M(b->l, M(b->r, c)));delete b;}
查 v 的排名
分裂出权值
注意用完要合并回去。
int R(int v) {T *a, *b;int s;S(r, v - 1, a, b);s = (a ? a->s : 0) + 1;r = M(a, b);return s;}
第 k 大,前驱,后继
和 BST 一样,不会影响性质。
int K(T *x, int v)
{
int z = x->l ? x->l->s : 0;if(v == z + 1) return x->v;
if(v <= z) return K(x->l, v);else return K(x->r, v - z - 1);
}
int P(T *x, int v)
{
if(!x) return -1e9;
if(v <= x->v) return P(x->l, v);
else return max(x->v, P(x->r, v));
}
int N(T *x, int v)
{
if(!x) return 1e9;
if(v >= x->v) return N(x->r, v);
else return min(x->v, N(x->l, v));
}
完整代码
#include <cstdio>
#include <cstdlib>
int max(int a, int b) {return a > b ? a : b;}
int min(int a, int b) {return a < b ? a : b;}
struct T
{
T *l, *r;int v, k, s;
T(int _v) : l(0), r(0), v(_v), k(rand()), s(1) {}
void p() {s = 1;if(l) s += l -> s;if(r) s += r -> s;}
}*r;
void S(T *x, int k, T *&a, T *&b)
{
if(!x) {a = b = 0;return;}
if(x->v > k) b = x, S(x->l, k, a, b->l), b->p();
else a = x, S(x->r, k, a->r, b), a->p();
}
T *M(T *a, T *b)
{
if(!a) return b;if(!b) return a;
if(a->k < b->k) {a->r = M(a->r, b);a->p();return a;}
else {b->l = M(a, b->l);b->p();return b;}
}
void I(int v) {T *a, *b;S(r, v, a, b);r = M(a, M(new T(v), b));}
void D(int v) {T *a, *b, *c;S(r, v, a, c);S(a, v - 1, a, b);r = M(a, M(b->l, M(b->r, c)));delete b;}
int R(int v) {T *a, *b;int s;S(r, v - 1, a, b);s = (a ? a->s : 0) + 1;r = M(a, b);return s;}
int K(T *x, int v)
{
int z = x->l ? x->l->s : 0;if(v == z + 1) return x->v;
if(v <= z) return K(x->l, v);else return K(x->r, v - z - 1);
}
int P(T *x, int v)
{
if(!x) return -1e9;
if(v <= x->v) return P(x->l, v);
else return max(x->v, P(x->r, v));
}
int N(T *x, int v)
{
if(!x) return 1e9;
if(v >= x->v) return N(x->r, v);
else return min(x->v, N(x->l, v));
}
int main()
{
srand(388651);int n, o, v;scanf("%d", &n);
while(n--)
{
scanf("%d%d", &o, &v);
switch(o)
{
case 1: I(v);break;
case 2: D(v);break;
case 3: printf("%d\n", R(v));break;
case 4: printf("%d\n", K(r, v));break;
case 5: printf("%d\n", P(r, v));break;
case 6: printf("%d\n", N(r, v));break;
}
}
return 0;
}
格式化的:
#include <cstdio>
#include <cstdlib>
int max(int a, int b) { return a > b ? a : b; }
int min(int a, int b) { return a < b ? a : b; }
struct T
{
T *l, *r;
int v, k, s;
T(int _v) : l(0), r(0), v(_v), k(rand()), s(1) {}
void p()
{
s = 1;
if (l)
s += l->s;
if (r)
s += r->s;
}
} * r;
void S(T *x, int k, T *&a, T *&b)
{
if (!x)
{
a = b = 0;
return;
}
if (x->v > k)
b = x, S(x->l, k, a, b->l), b->p();
else
a = x, S(x->r, k, a->r, b), a->p();
}
T *M(T *a, T *b)
{
if (!a)
return b;
if (!b)
return a;
if (a->k < b->k)
{
a->r = M(a->r, b);
a->p();
return a;
}
else
{
b->l = M(a, b->l);
b->p();
return b;
}
}
void I(int v)
{
T *a, *b;
S(r, v, a, b);
r = M(a, M(new T(v), b));
}
void D(int v)
{
T *a, *b, *c;
S(r, v, a, c);
S(a, v - 1, a, b);
r = M(a, M(b->l, M(b->r, c)));
delete b;
}
int R(int v)
{
T *a, *b;
int s;
S(r, v - 1, a, b);
s = (a ? a->s : 0) + 1;
r = M(a, b);
return s;
}
int K(T *x, int v)
{
int z = x->l ? x->l->s : 0;
if (v == z + 1)
return x->v;
if (v <= z)
return K(x->l, v);
else
return K(x->r, v - z - 1);
}
int P(T *x, int v)
{
if (!x)
return -1e9;
if (v <= x->v)
return P(x->l, v);
else
return max(x->v, P(x->r, v));
}
int N(T *x, int v)
{
if (!x)
return 1e9;
if (v >= x->v)
return N(x->r, v);
else
return min(x->v, N(x->l, v));
}
int main()
{
srand(388651);
int n, o, v;
scanf("%d", &n);
while (n--)
{
scanf("%d%d", &o, &v);
switch (o)
{
case 1:
I(v);
break;
case 2:
D(v);
break;
case 3:
printf("%d\n", R(v));
break;
case 4:
printf("%d\n", K(r, v));
break;
case 5:
printf("%d\n", P(r, v));
break;
case 6:
printf("%d\n", N(r, v));
break;
}
}
return 0;
}
分类:
未分类
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具