首页 > 其他分享 >Treap

Treap

时间:2023-10-23 21:34:57浏览次数:28  
标签:return int siz Treap lson 节点

概述

FHQ Treap 基于 Treap 发明的“无旋 Treap”,代码短,易理解且速度快(在 OI 算是很优秀的算法了)。

FHQ Treap 核心函数只有两个,分别是 分裂合并。字面意思,就是将某一棵二叉查找树按某种要求分裂成两个或将两个合并成一个。

实现

变量维护

变量名 功能
root 记录所维护平衡树的根节点编号
cnt 节点总数
lson[i] 编号为 i 的节点的左儿子的编号
rson[i] 编号为 i 的节点的右儿子的编号
val[i] 编号为 i 的节点的值
siz[i] 编号为 i 的节点的子树的大小
cmp[i] 下文介绍

函数

分裂

通常分为按 v 合并或按 siz 合并。按 v 合并时,将小于等于 v 的和大于 v 分裂成两棵树。按 siz 分裂即将从小到大排前 siz 的和 siz 之后的分裂成两棵树。

以按 v 分裂的为例(另一类同理)。函数的参数有四个,分别为 u、v、x、y,分别代表当前节点,v(具体含义见上),以及分裂成的两个树的待接入的位置的地址。

若当前节点为 u ,则分为两种情况:

  1. 若 \(val[u] \leq v\),则将 u 接到树 x 下面, 继续分裂 rson[u]。
  2. 若 \(val[u] > v\),则将 u 接到树 y 下面,继续分烈 lson[u]。

代码片段:

void Split(int u, int v, int &x, int &y) {
	if(!u) {x = y = 0; return;}
	if(val[u] <= v) x = u, Split(rson[u], v, rson[u], y);
	else y = u, Split(lson[u], v, x, lson[u]);
	PushUp(u);
}

合并

将两个子树合并成一棵树并返回根节点编号。为了防止极端情况两棵树合并后变成一条链(反正就是防止深度很大导致退化),类似 Treap 中的操作,我们给每个节点随机分配一个值 cmp,用来优化。

代码片段:

int Merge(int x, int y) {
	if(!x || !y) return x + y;
	if(cmp[x] < cmp[y]) {
		rson[x] = Merge(rson[x], y);
		PushUp(x);
		return x;
	}
	else {
		lson[y] = Merge(x, lson[y]);
		PushUp(y);
		return y;
	}
}

查询第 K 大

很好想,跟值域线段树查询第 K 大差不多。

代码片段:

int Get_Kth(int u, int k) {
	if(k <= siz[lson[u]]) return Get_Kth(lson[u], k);
	if(k == siz[lson[u]] + 1) return u;
	if(k >= siz[lson[u]] + 2) return Get_Kth(rson[u], k - siz[lson[u]] - 1);
	return 0;
}

操作

基本所有平衡树的操作都能通过这三个函数实现,方法琢磨一下就出来了。

End

标签:return,int,siz,Treap,lson,节点
From: https://www.cnblogs.com/TS357051/p/17783531.html

相关文章

  • 算法笔记(2)FHQtreap
    原发布于我的个人博客前言FHQtreap绝对是平衡树里最好写,最实用的,他几乎能做所有splay或其它平衡树能做的事,还能可持久化!这篇文章将会介绍FHQtreap的基本操作和维护区间的操作,并附上例题。基本操作FHQtreap的基本操作只有两个,分裂和合并。有些读者可能会问,分裂和合并和平衡树......
  • 【学习笔记】FHQ-Treap
    前置知识:二叉搜索树与二叉堆。1.简介Treap,即Tree+Heap,它的每个结点上存储着一个索引\(key\)和一个值\(val\),其中索引满足二叉堆的性质,值满足二叉搜索树的性质,且索引是随机的。Treap就是通过上述的性质,使树达到平衡。至于为什么索引是随机的,其实很简单:我们插入的每个数的......
  • Atcoder Beginner Contest 324 G Generate Arrays 题解-Treap
    为了更好的阅读体验,请点击这里题目链接套上平衡树板子就能做的很快的题,然后因为是指针存树,因此交换只需要把序列大小较小的挨个拿出来插到相应的地方即可。复杂度\(O(N\log^2N)\)。但是一定要记住不可以直接使用std::swap交换包含带有指针的类的实例(如代码中的Treap类)!......
  • Treap引入
    前置知识treap是由BST和heap组合而成的数据结构,这一点也体现在它的名字上:treap=tree+heapBST中,每个节点的左儿子都比它小,右儿子都比它大,可以实现有序的遍历,但是可能因为数据特殊的排列方式,而退化为线性heap中,每个父节点都是当前子树内权值最大(或最小)的点。在BST的基础上加一个......
  • BST-Treap名次树指针实现板子 Ver2.0
    为了更好的阅读体验,请点击这里这里只有板子没有原理QWQ可实现1.插入x数2.删除x数(若有多个相同的数,只删除一个)3.查询x数的排名(排名定义为比当前数小的数的个数+1)4.查询排名为x的数5.求x的前驱(前驱定义为小于x,且最大的数)6.求x的后继(后继定义为大于x,且......
  • 弱势无图解FHQ-Treap 及各种乱七八糟的错误方法
    众所周知,FHQ-Treap是一个码量少,可区间翻转,能持久化的treap(只是常熟略大)像我这种蒟蒻,想调处有旋Treap或者Splay肯定要个114514年以下可能以FHQ代表FHQ-Treap(逃前置芝士treap的节点拥有两个权值,一个是值,一个是优先级。优先级满足堆的性质,值满足二叉搜索树的性质。当两个权值相......
  • Treap
    BST\(v_i\)表示点权,\(x\)表示当前点,\(L\)表示左子树,\(R\)表示右子树在普通二叉树的基础上多一个条件对于\(p\inL\),满足\(v_p\leqv_x\)对于\(q\inR\),满足\(v_x<v_q\)Treap但是这样如果BST是一条链的话就退化\(O(n)\),而且很容易卡,考虑TreapTreap就是在普通B......
  • FHQ-Treap 详解
    目录1)FHQ-Treap基本功能理论与实现1.1)FHQ-Treap模型1.2)操作一:分裂(Split)1.3)操作二:合并(Merge)1.4)操作三:插入新节点1.5)删除某个节点1.6)查询某个值的排名1.7)查询排名为\(k\)的值1.8)查询\(x\)的前驱与后继1.9)Endofthisunit2)FHQ-Treap的应用2.1)洛谷P3369END1)FHQ-Treap基本功......
  • 『学习笔记』fhq-treap
    啥是平衡树这边建议去这里。分裂一般指的是按值分裂,意思就是以树上的BST(二叉搜索树)的值为关键值分裂。一般会给一个关键值\(val\),把一棵平衡树分裂成BST值\(\leqval\)和\(>val\)的两部分。主要思想从根开始递归,递归到某一节点,如果当前根节点的BST值小于等于你给的那......
  • 无旋平衡树(范浩强Treap)平均时间复杂度证明
    范浩强Treap是一种应用广泛的数据结构(可参考OI_Wiki),然而网上难以找到比较严谨的复杂度证明.本文将严格证明\(n\)个结点的Treap的期望树高为\(\Theta(\logn)\),由于一次分裂或合并操作的递归深度恰为树高,这便说明了一次操作的平均时间复杂度为\(\Theta(\logn)\).首先,由......