FHQ treap学习(复习)笔记
.....好吧....最后一篇学习笔记的flag它倒了.....
好吧,这篇笔记也鸽了好久好久了...
比赛前刷模板,才想着还是补个坑吧...
FHQ,这个神仙(范浩强大佬),发明了这个神仙的数据结构,
首先,本篇博客使用洛谷普通平衡树为背景,即
- 查找前驱
- 查找后记
- 查找kth的数
- 查找k的排名
- 插入一个数
- 删除一个数
FHQ treap,是一个treap,它还是和treap一样,是tree+heap,所以它也有一个键值维护堆的性质。
它可以干任何treap和Splay能干的事。
它的实现主要由两个函数实现:
merge:把两棵树合并成一棵
split:把树分割成两棵
在这里介绍两个函数的实现方法:
merge

可以看到,它把两棵树合并了起来,但是并不是简单地接起来,而是打散,重新组合。
代码:
int merge(int x,int y)//把xy为根的两棵子树给合并
{
if(!x||!y)//如果一边没了
return x+y;//就返回
if(t[x].key<t[y].key)//维护key值,如果x的key值小于y的k值
{
t[x].son[]=merge(t[x].son[],y);//说明此时一定不符合堆性质,把x的右儿子和y合并
update(x);//更新相关变量
return x;//返回根节点
}
else
{
t[y].son[]=merge(x,t[y].son[]);//同上
update(y);
return y;
}
}
通过这样一个递归,不断拆分节点&&合并的过程中,就建立了一棵新树。
split:

从上图可得:(把树从5分开)
split的过程就是把树拆分成左右树,左树所有节点权值都小于k,右树的节点权值都大于k。
怎么实现呢?
代码:
void split(int now,int k,int &x,int &y)//把一棵树now给从k分割成x和y
{
if(!now) x=y=;//如果没有了,就返回
else
{
if(t[now].v<=k) //如果当前点的权值小于k,它应该在左子树
{
x=now;//更新
split(t[now].son[],k,t[now].son[],y);分割右儿子,找一个可能的更大的
}
else//同上
{
y=now;
split(t[now].son[],k,x,t[now].son[]);
}
update(now);
}
}
这样,我们就可以干以上的事了。
前置:查找kth
因为建立的事一个二叉查找树,所以还是可以像遍历二叉查找树那样查找kth的。
代码十分简单
int kth(int now,int k)
{
while()
{
if(k<=t[t[now].son[]].size)
now=t[now].son[];
else
{
if(k==t[t[now].son[]].size+)
return now;
else
{
k-=t[t[now].son[]].size+;
now=t[now].son[];
}
}
}
}
然后就可以A掉普通平衡树了。
插入新节点:首先暴力新建一个节点
int new_node(int k)
{
tot++;
t[tot].size=;
t[tot].v=k;
t[tot].key=rand();
return tot;
}
然后把树从k地方断开,把新节点看做一棵树,把它和上下树合在一起就行了
split(rt,a,x,y);
rt=merge(merge(x,new_node(a)),y);
删除节点:
把树从k断开,然后把左树从k-1断开,然后把上下树给合并,把k节点扔了就行了
split(rt,a,x,z);
split(x,a-,x,y);
y=merge(t[y].son[],t[y].son[]);
rt=merge(merge(x,y),z);
查找排名:
把树从k分开,则k所在的数的size即使排名
split(rt,a-,x,y);
printf("%d\n",t[x].size+);
rt=merge(x,y);
查找kth:
直接用kth函数即可
printf("%d\n",t[kth(rt,a)].v);
前驱:
把树从k分开,则size-1大小的那个kth点就是前驱
split(rt,a-,x,y);
printf("%d\n",t[kth(x,t[x].size)].v);
rt=merge(x,y);
后继:同上
split(rt,a,x,y);
printf("%d\n",t[kth(y,)].v);
rt=merge(x,y);
完整高清无码代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+;
struct tree
{
int son[],v,key,size;
}t[maxn];
int tot=,rt=;
void update(int p)
{
t[p].size=t[t[p].son[]].size+t[t[p].son[]].size+;
}
int new_node(int k)
{
tot++;
t[tot].size=;
t[tot].v=k;
t[tot].key=rand();
return tot;
}
int merge(int x,int y)//o?2¢ò?x£?y?a?ùμ?á???×óê÷
{
if(!x||!y)
return x+y;
if(t[x].key<t[y].key)
{
t[x].son[]=merge(t[x].son[],y);
update(x);
return x;
}
else
{
t[y].son[]=merge(x,t[y].son[]);
update(y);
return y;
}
}
void split(int now,int k,int &x,int &y)//ò?è¨?μk·?à?nowê÷3éx,y
{
if(!now) x=y=;
else
{
if(t[now].v<=k) //°??ùóDD?óúkμ?è¨?μμ??úμ?·?μ?ò???ê÷?D
{
x=now;
split(t[now].son[],k,t[now].son[],y);
}
else
{
y=now;
split(t[now].son[],k,x,t[now].son[]);
}
update(now);
}
}
int kth(int now,int k)
{
while()
{
if(k<=t[t[now].son[]].size)
now=t[now].son[];
else
{
if(k==t[t[now].son[]].size+)
return now;
else
{
k-=t[t[now].son[]].size+;
now=t[now].son[];
}
}
}
}
int x,y,z,n;
int main()
{
srand((unsigned)time(NULL));
scanf("%d",&n);
int flag,a,b,c;
for(int i=;i<=n;i++)
{
scanf("%d",&flag);
scanf("%d",&a);
if(flag==)
{
split(rt,a,x,y);
rt=merge(merge(x,new_node(a)),y);
}
if(flag==)
{
split(rt,a,x,z);
split(x,a-,x,y);
y=merge(t[y].son[],t[y].son[]);
rt=merge(merge(x,y),z);
}
if(flag==)
{
split(rt,a-,x,y);
printf("%d\n",t[x].size+);
rt=merge(x,y);
}
if(flag==)
{
printf("%d\n",t[kth(rt,a)].v);
}
if(flag==)
{
split(rt,a-,x,y);
printf("%d\n",t[kth(x,t[x].size)].v);
rt=merge(x,y);
}
if(flag==)
{
split(rt,a,x,y);
printf("%d\n",t[kth(y,)].v);
rt=merge(x,y);
}
}
return ;
}
FHQ treap学习(复习)笔记的更多相关文章
- fhq treap 学习笔记
序 今天心血来潮,来学习一下fhq treap(其实原因是本校有个OIer名叫fh,当然不是我) 简介 fhq treap 学名好像是"非旋转式treap及可持久化"...听上去怪 ...
- 强化学习复习笔记 - DEEP
Outline 激活函数 使用逼近器的特点: 较少数量的参数表达复杂的函数 (计算复杂度) 对一个权重的调整可以影响到很多的点 (泛化能力) 多种特征表示和逼近器结构 (多样性) 激活函数 Sigmo ...
- 「FHQ Treap」学习笔记
话说天下大事,就像fhq treap —— 分久必合,合久必分 简单讲一讲.非旋treap主要依靠分裂和合并来实现操作.(递归,不维护fa不维护cnt) 合并的前提是两棵树的权值满足一边的最大的比另一 ...
- 「学习笔记」 FHQ Treap
FHQ Treap FHQ Treap (%%%发明者范浩强年年NOI金牌)是一种神奇的数据结构,也叫非旋Treap,它不像Treap zig zag搞不清楚(所以叫非旋嘛),也不像Splay完全看不 ...
- Fhq Treap [FhqTreap 学习笔记]
众所周知 Fhq Treap 是 fhq 神仙研究出来的平衡树- 具体实现 每个点实现一个 \(\text{rnd}\) 表示 rand 的值 为什么要 rand 呢 是为了保证树高为 \(\log ...
- FFT/NTT复习笔记&多项式&生成函数学习笔记Ⅲ
第三波,走起~~ FFT/NTT复习笔记&多项式&生成函数学习笔记Ⅰ FFT/NTT复习笔记&多项式&生成函数学习笔记Ⅱ 单位根反演 今天打多校时 1002 被卡科技了 ...
- treap学习笔记
treap是个很神奇的数据结构. 给你一个问题,你可以解决它吗? 这个问题需要treap这个数据结构. 众所周知,二叉查找树的查找效率低的原因是不平衡,而我们又不希望用各种奇奇怪怪的旋转来使它平衡,那 ...
- fhq treap抄袭笔记
目录 碎碎念 点一下 注意!!! 模板 fhq treap 碎碎念 我咋感觉合并这么像左偏树呢 ps:难道你们的treap都是小头堆的吗 fhq真的是神人 现在看以前学的splay是有点恶心,尤其是压 ...
- fhq treap最终模板
新学习了fhq treap,厉害了 先贴个神犇的版, from memphis /* Treap[Merge,Split] by Memphis */ #include<cstdio> # ...
随机推荐
- Python多任务之协程
前言 协程的核心点在于协程的使用,即只需要了解怎么使用协程即可:但如果你想了解协程是怎么实现的,就需要了解依次了解可迭代,迭代器,生成器了: 如果你只想看协程的使用,那么只需要看第一部分内容就行了:如 ...
- Git学习记录-基本命令篇
目录 网页在线练习地址 https://learngitbranching.js.org/ 1.git commit Git 仓库中的提交记录保存的是你的目录下所有文件的快照,就像是把整个目录复制,然 ...
- C语言--最大公约数
//辗转相除法 int main() { int a,b; int t; scanf("%d %d", &a,&b); ) { t = a%b; a = b; b ...
- SpringMVC快速入门记录(二)
一.数组参数绑定和List参数绑定 1.数组参数绑定 提交多个相同name的参数,保持name的名字和Controller方法参数的数组名称相同即可. 2.List参数绑定 List中存放对象,并将定 ...
- 支撑微博亿级社交平台,小白也能玩转Redis集群(原理篇)
Redis作为一款性能优异的内存数据库,支撑着微博亿级社交平台,也成为很多互联网公司的标配.这里将以Redis Cluster集群为核心,基于最新的Redis5版本,从原理再到实战,玩转Redis集群 ...
- postman环境变量设置
1.点击小齿轮进入到环境变量添加页面,点击add添加环境变量 2.输入变量名称和变量值 3.添加成功 4.接口中设置变量
- 「看完不后悔系列!」Maya的建模小技巧
Maya 将最大的联合影响力降至最低 最大的联合影响力是游戏角色装备的已知要求. 但是,对于每种类型的生产来说,这实际上都是一个很好的工作流程. 从透视图上看,如果你将联合影响力从4更改为5,则不一定 ...
- 后门免杀工具-Backdoor-factory
水一水最近玩的工具 弄dll注入的时候用到的 介绍这款老工具 免杀效果一般..但是简单实用 目录: 0x01 backdoor-factory简介 0x02 特点功能 0x03 具体参数使用 PS: ...
- 基于常规DNS隧道进行的tcp端口转发dns2tcp的使用
0x01 安装Dns2TCP dns2tcp 是一个利用DNS隧道转发TCP连接的工具,使用C语言开发. sudo apt-get install dns2tcp 0x02配置dns2tcp 配置DN ...
- js中submit和button的区别
今天写一个js验证 遇到点小坑 记录一下 button-普通按钮,submit-提交按钮. submit是button的一个特例,也是button的一种,它把提交这个动作自动集成了,submit和bu ...