神仙数据结构——FHQ_Treap
$FHQ\_Treap$是平衡树的一种,它不仅支持几乎所有的平衡树的操作,而且实现特别简单,总共只有两个操作。这里来简单介绍一下。
基本操作
$FHQ\_Treap$和$Treap$一样是需要用随机值来维护树的形态的,但是$FHQ\_Treap$不需要旋转来调整形态,而是用$Split$和$Merge$来实现,也就是分离与合并,也就是这两种操作,完成了$FHQ\_Treap$的所有操作。
分离(Split)
把一棵平衡树分离成两棵,从而方便插入和删除。分离有两种做法,一种是按权值分离,一种是按子树大小分离,根据情况选择。
权值分离版:
void split(int rt,int k,int &x,int &y)
{
if( !rt ) x=y=;
else {
if( val[rt]<=k ) x=rt, split(ch[rt][],k,ch[rt][],y);
else y=rt, split(ch[rt][],k,x,ch[rt][]);
pushup(rt);
}
}
子树大小版:
void split(int rt,int k,int &x,int &y)
{
if( !rt ) x=, y=;
else {
pushdown(rt);
if( siz[ch[rt][]]<k ) {
x=rt, split(ch[rt][],k-siz[ch[rt][]]-,ch[rt][],y);
} else {
y=rt, split(ch[rt][],k,x,ch[rt][]);
}
pushup(rt);
}
}
合并(merge)
合并操作与左偏树的合并类似,按照优先级合并,把优先级高的作为父节点。当然,合并的时候,函数中的两个参数$x,y$要按照顺序,$x$是权值较小的,$y$是权值较大的,因为合并的时候是按照随机值来确定优先级的。(当然在函数中交换也行,不过常数大些)
int merge(int x,int y)
{
if( !x || !y ) return x+y;
if( p[x]<p[y] ) {
ch[x][]=merge(ch[x][],y); pushup(x);
return x;
} else {
ch[y][]=merge(x,ch[y][]); pushup(y);
return y;
}
}
平衡树的其他操作的实现
插入新节点(insert)
先把树按照新结点的权值分离,然后再把新结点当作一棵树与两个分离出来的树合并。
inline int neo(int v)
{
val[++tot]=v;
siz[tot]=; p[tot]=rand();
return tot;
} inline void insert(int v)
{
int x,y;
split(root,v,x,y);
root=merge(merge(x,neo(v)),y);
}
删除节点(delete)
按删除节点的权值$v$把树分离成小于$v$,等于$v$,大于$v$三段,然后去掉等于$v$的树的根节点(也就是直接合并根节点的左右子树),然后合并回来。
inline void delet(int v)
{
int x,y,z;
split(root,v,x,y);
split(x,v-,x,z);
z=merge(ch[z][],ch[z][]);
root=merge(x,merge(z,y));
}
查询权值为$k$的节点排名
按照权值分离然后输出左子树大小$+1$即可。
inline void kth(int k)
{
int x,y;
split(root,k-,x,y);
printf("%d\n",siz[x]+);
root=merge(x,y);
}
查询$k$小值
和其他平衡树一样搜索、递归。
int rank(int rt,int k)
{
if( siz[ch[rt][]]==k- ) return val[rt];
if( siz[ch[rt][]]>=k ) return rank(ch[rt][],k);
return rank(ch[rt][],k-siz[ch[rt][]]-);
}
查询前驱后继
按权值分离然后查询分离出的子树的最大/最小值就行了。
inline void prev(int v)
{
int x,y;
split(root,v-,x,y);
printf("%d\n",rank(x,siz[x]));
root=merge(x,y);
} inline void nex(int v)
{
int x,y;
split(root,v,x,y);
printf("%d\n",rank(y,));
root=merge(x,y);
}
可以看出,$FHQ\_Treap$的操作都非常简短,仅仅用了两种核心操作就实现了其他平衡树的能实现的全部功能,非常方便。在绝大多数情况下需要使用平衡树的时候都可以直接用$FHQ\_Treap$,既容易理解又方便实现,而且也很容易$Debug$。
同时,$FHQ\_Treap$也是支持可持久化的,不过这里就不再赘述(我会告诉你其实我也没写过?)。
完整模板
//It is made by HolseLee on 27th Sep 2018
//Luogu.org P3369
#include<bits/stdc++.h>
using namespace std; const int N=1e5+;
int n,root,tot;
int val[N],ch[N][],p[N],siz[N]; inline int read()
{
char ch=getchar(); int num=; bool flag=false;
while( ch<'' || ch>'' ) {
if( ch=='-' ) flag=true; ch=getchar();
}
while( ch>='' && ch<='' ) {
num=num*+ch-''; ch=getchar();
}
return flag ? -num : num;
} inline void pushup(int rt)
{
siz[rt]=siz[ch[rt][]]+siz[ch[rt][]]+;
} void split(int rt,int k,int &x,int &y)
{
if( !rt ) x=y=;
else {
if( val[rt]<=k ) x=rt, split(ch[rt][],k,ch[rt][],y);
else y=rt, split(ch[rt][],k,x,ch[rt][]);
pushup(rt);
}
} int merge(int x,int y)
{
if( !x || !y ) return x+y;
if( p[x]<p[y] ) {
ch[x][]=merge(ch[x][],y); pushup(x);
return x;
} else {
ch[y][]=merge(x,ch[y][]); pushup(y);
return y;
}
} inline int neo(int v)
{
val[++tot]=v;
siz[tot]=; p[tot]=rand();
return tot;
} inline void insert(int v)
{
int x,y;
split(root,v,x,y);
root=merge(merge(x,neo(v)),y);
} inline void delet(int v)
{
int x,y,z;
split(root,v,x,y);
split(x,v-,x,z);
z=merge(ch[z][],ch[z][]);
root=merge(x,merge(z,y));
} inline void kth(int k)
{
int x,y;
split(root,k-,x,y);
printf("%d\n",siz[x]+);
root=merge(x,y);
} int rank(int rt,int k)
{
if( siz[ch[rt][]]==k- ) return val[rt];
if( siz[ch[rt][]]>=k ) return rank(ch[rt][],k);
return rank(ch[rt][],k-siz[ch[rt][]]-);
} inline void prev(int v)
{
int x,y;
split(root,v-,x,y);
printf("%d\n",rank(x,siz[x]));
root=merge(x,y);
} inline void nex(int v)
{
int x,y;
split(root,v,x,y);
printf("%d\n",rank(y,));
root=merge(x,y);
} int main()
{
srand();
n=read(); int opt;
for(int i=; i<=n; ++i) {
opt=read();
if( opt== ) insert(read());
else if( opt== ) delet(read());
else if( opt== ) kth(read());
else if( opt== ) printf("%d\n",rank(root,read()));
else if( opt== ) prev(read());
else nex(read());
}
return ;
}
神仙数据结构——FHQ_Treap的更多相关文章
- fhq_treap 学习笔记
前言:昨天写NOIp2017队列,写+调辗转了3h+,不知道怎么的,就点进了一个神仙的链接,便在今日学习了神仙的fhq_treap. 简介:fhq_treap功能强大,支持splay支持的所有操作,代 ...
- 浅谈左偏树在OI中的应用
Preface 可并堆,一个听起来很NB的数据结构,实际上比一般的堆就多了一个合并的操作. 考虑一般的堆合并时,当我们合并时只能暴力把一个堆里的元素一个一个插入另一个堆里,这样复杂度将达到\(\log ...
- 【题解】P4247 [清华集训]序列操作(线段树修改DP)
[题解]P4247 [清华集训]序列操作(线段树修改DP) 一道神仙数据结构(DP)题. 题目大意 给定你一个序列,会区间加和区间变相反数,要你支持查询一段区间内任意选择\(c\)个数乘起来的和.对1 ...
- fhq-treap简介
\(fhq-treap\)是个好东西啊!无旋转\(treap\)果然是好写,而且还是比较好理解的. 这种数据结构是由神犇fhq发明的.\(Think\ functional!\) fhq神犇说,函数式 ...
- thupc & cts & apio & thusc 游记 (北京17日游记)
thupc & cts & apio & thusc 游记 (北京17日游记) Day 0 和隔壁校两人py了一下,六个人组了两队,(左哼哼)与(右哼哼),我和Camoufla ...
- [日常] SNOI2019场外VP记
SNOI2019场外VP记 教练突然说要考一场别省省选来测试水平...正好还没看题那就当VP咯w... Day 1 八点开题打 .vimrc. 先看了看题目名...一股莫名鬼畜感袭来... 怎么T1就 ...
- 冲刺CSP-S集训考试反思+其它乱写(密码私信)
RT.开坑. 10.1 开门黑23333. 放假回来稍困,而且感冒似乎愈加严重,导致我正常考试基本睁不开眼.一个小时勉强把题读懂,神志恍惚如斯. 看T2觉得估计又是各种推柿子堆定理的数学大题,写了个暴 ...
- csp-s模拟测试52-53
留坑.... 改完题再说吧. 留坑....最近考得什么鬼??模拟53T1 u(差分) 一道差分题????然而考场没有想到如何维护斜率上的差分,事后经miemeng和cyf的生(xuan)动(xue)讲 ...
- 2021.8.24考试总结[NOIP47]
T1 prime 发现只需筛小于等于$mid(\sqrt r,k)$的质数,之后用这些质数筛掉区间内不合法的数即可. $code:$ 1 #include<bits/stdc++.h> 2 ...
随机推荐
- Mountainous landscape
Description 现在在平面上给你一条折线 \(P_1P_2 \cdots P_n\) . \(x\) 坐标是严格单调递增的.对于每一段折线 \(P_iP_{i+1}\) ,请你找一个最小的 \ ...
- BZOJ2322 [BeiJing2011]梦想封印 【set + 线性基】
题目链接 BZOJ2322 题解 鉴于BZOJ2115,要完成此题,就简单得多了 对图做一遍\(dfs\),形成\(dfs\)树,从根到每个点的路径形成一个权值,而每个返祖边形成一个环 我们从根出发去 ...
- 动态dp 板子
动态dp 瞎扯两句吧 先从序列上理解,维护链的最大独立集. 考虑是从左边转移的,那么矩阵的转移唯一,直接放在线段树上就可以了. 放在树上的话,儿子都可以转移,把轻儿子的转移放在子链链头更新,然后每条链 ...
- SpringBoot整合Mybatis之Annotation
首先需要下载前面一篇文章的代码,在前一章代码上进行修改. SpringBoot整合Mybatis(注解方式) 复制前一个项目,修改配置文件,mybatis的相关配置为: mybatis: type-a ...
- 【洛谷P1462】通往奥格瑞玛的道路
题目大意:给定一个 N 个点,M 条边的无向图,求从 1 号节点到 N 号节点的路径中,满足路径长度不大于 B 的情况下,经过顶点的点权的最大值最小是多少. 题解:最大值最小问题一般采用二分答案.这道 ...
- P3861 8月月赛A
https://www.luogu.org/problemnew/show/P3861 排序:乘数保持单调递增 dp+hash(map解决) #include <cstdio> #incl ...
- 说说Cookie和Session
Session和Cookie在网站开发中是用来保存用户与后端服务器的交互状态.它们有各自的缺点和优点.而且,他们的优点和应用场景是对立的. Cookie 完整地描述:当一个用户通过HTTP访问一个 ...
- 纯CSS实现表单验证
ladies and 乡亲们,表单验证你在做吗?客户端or服务器端,javascript or jquery,动手写 or 使用插件,今天我们来探索下使用纯css实现表单验证,借以学习css sele ...
- LaTeX文章结构
%导言 %\documentclass{article} %ctexbook \documentclass{ctexbook} \title{\heiti 监督学习} % 黑体 \author{\ka ...
- [整理]ASP.NET MVC 5
1.入门 1.1官方资料 http://www.asp.net/mvc/overview/getting-started/introduction/getting-started 疑问: startu ...