fhq treap 学习笔记
前言
这是一个在很久很久以前学了的知识点
当时是一坨平衡树一起学的,学了替罪羊,fhq,splay
然后当时听说 splay 更牛逼,而且维护 LCT 需要 splay,就不管其他两个平衡树了,然后就忘了怎么写 fhq 了(雾)
后面发现 splay 这个东西又臭又长,写起来要调一年
加上同机房的人疯狂安利 fhq treap,就来学了一下
发现是真的简单,好写,好用(真香)
正片
对于一个点,你需要用于维护平衡树的基本信息有 ch[2],size,val,rnd 其他的根据题目再定
其中 ch[0/1] 是左右儿子,size 是子树大小,rnd 是一个随机的值
split
核心操作之一
有两种 split,第一种是根据权值 split,第二种是根据 rank split
大同小异,给出第一种的详细说明
void split(int node,int val,int &x,int &y)
表示把 的子树分成 和 两部分,分别存入
核心思想是根据 的节点状态分开
给出实现
void split(int node,int val,int &x,int &y)
{
if (!node) return x=y=0,void();
if (t[node].val<=val)
{
x=node;
split(t[node].ch[1],val,t[x].ch[1],y);
}
else
{
y=node;
split(t[node].ch[0],val,x,t[node].ch[0]);
}
push_up(node);
}
merge
核心操作之二
int merge(int x,int y)
用于把 的子树合并成一棵数,并返回节点值
注意这里要保证 中所有的节点按照 cmp 都严格不小于 中所有的节点
实现过程中用了随机的性质,所以生成的树高期望是 的
给出实现
int merge(int x,int y)
{
if (!x||!y) return x+y;
if (t[x].rnd<t[y].rnd)
{
t[x].ch[1]=merge(t[x].ch[1],y);
push_up(x);
return x;
}
else
{
t[y].ch[0]=merge(x,t[y].ch[0]);
push_up(y);
return y;
}
}
注意不要作死写 ,这样会被卡,虽然我也不知道为什么(
其他
fhq treap 的基本操作就是上面两个,其他操作都可以用上面两个操作乱搞实现
如果你清楚二叉搜索树的性质,那么理解这两个玩意就可以了(
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端