treap 简述
treap 的功能齐全, 插入删除,分裂合并……。
这里介绍一点基础操作, 以后会补更多操作。
以下键值均指满足二叉查找树性质的节点参数。
以下 rnd 均满足大根堆性质。
节点
struct node {
int siz, val, rnd, c[2];
// val 是键值, siz 是子树节点个数
// rnd 是某个随机数, c[0/1] 是 左/右 子节点
node() {}
node(int s, int v) : siz(s), val(v) {
rnd = rand();
c[0] = c[1] = 0;
}
} t[N];
int tot, root;
inline void upd (int me) {
t[me].siz = t[t[me].c[0]].siz + t[t[me].c[1]].siz + 1;
}
一般来说初始化只会用到 size 和 val 两个参数。
旋转插入删除
旋转涉及三个指针, 因为把 x 的子节点悬上来, 需要改变之前 x 的父亲的指针, 关于这个, 如果在插入函数中使用传址参数, 节点就可以不用维护指向父亲的指针了。
删除就是把点悬到可以简便删除的地方, 复杂度与树高相关, 在删除的过程中需要注意维护 rnd 的堆性质。
treap 可以不 fatnode, 说人话就是 treap 里可以存在多个键值相同的点。
void ro (int & me, int dir) {
int y = t[me].c[dir];
t[me].c[dir] = t[y].c[dir ^ 1], t[y].c[dir ^ 1] = me;
upd (me), upd (y);
me = y;
}
void ins (int x, int & me) {
if (! me) {
t[me] = node (1, x);
return ;
}
++ t[me].siz;
int dir = x > t[me].val;
ins (x, t[me].c[dir]);
if (t[t[me].c[dir]].rnd > t[me].rnd) ro (me, dir);
}
void del (int x, int & me) {
if (! me) return ;
if (t[me].val == x) {
if (!t[me].c[0] || !t[me].c[1]) me = t[me].c[0] | t[me].c[1];
else {
int dir = t[t[me].c[1]].rnd > t[t[me].c[0]].rnd;
ro (me, dir);
-- t[me].siz;
del (x, t[me].c[dir ^ 1]);
}
} else {
-- t[me].siz;
del (x, t[me].c[x > t[me].val]);
}
}
rnk、kth 和前驱后继
这里 rnk(x) 定义为小于 x 的数的数量 + 1, kth(x) 定义为最大的 rnk ≤ x 的数。
x 的前驱 pre(x) 定义为最大的小于 x 的数, 后继 nxt(x) 则定义为最小的大于 x 的数。(都是严格的)
不过比较显然地,pre(x) = kth (rnk (x) - 1),nxt(x) = kth (rnk (x + 1)) 。
这里给出 rnk 和 kth 的实现(这里的代码, fid 就是 kth):
int fid (int x, int me) {
int now = t[t[me].c[0]].siz + 1;
if (x == now) return t[me].val;
return x < now ? fid (x, t[me].c[0]) : fid (x - now, t[me].c[1]);
}
int rnk (int x, int me) {
if (! me) return 1;
return x > t[me].val ? t[t[me].c[0]].siz + 1 + rnk (x, t[me].c[1]) : rnk (x, t[me].c[0]);
}
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core GC压缩(compact_phase)底层原理浅谈
· 现代计算机视觉入门之:什么是图片特征编码
· .NET 9 new features-C#13新的锁类型和语义
· Linux系统下SQL Server数据库镜像配置全流程详解
· 现代计算机视觉入门之:什么是视频
· Sdcb Chats 技术博客:数据库 ID 选型的曲折之路 - 从 Guid 到自增 ID,再到
· .NET Core GC压缩(compact_phase)底层原理浅谈
· Winform-耗时操作导致界面渲染滞后
· Phi小模型开发教程:C#使用本地模型Phi视觉模型分析图像,实现图片分类、搜索等功能
· 语音处理 开源项目 EchoSharp