首页 > 其他分享 >FHQ-Treap

FHQ-Treap

时间:2025-01-12 20:10:35浏览次数:6  
标签:return merge int void Treap split FHQ ls

简介

基于分裂与合并的 Treap。

操作

split

按权值分裂:

inline void split(int p, int k, int &x, int &y) {// p 表示当前分裂树的根节点,x,y 表示分裂成的两棵树的根节点,k 为关键字
	if(! p) return x = y = 0, void();

	if(val[p] <= k) {
		x = p;
		split(rs[p], k, rs[p], y);
	}
	else {
		y = p;
		split(ls[p], k, x, ls[p]);
	}

	psup(p);
}

按排名分裂:

inline void split(int p, int k, int &x, int &y) {
	if(! p) return x = y = 0, void();

	if(sz[ls[p]] >= k) {
		y = p;
		split(ls[p], k, x, ls[p]);
	}
	else {
		x = p;
		split(rs[p], k - sz[ls[p]] - 1, rs[p], y);
	}

	psup(p);

	return ;
}

两种写法并非完全相同,需要看要求仔细斟酌。

merge

inline int merge(int x, int y) {
	if(! x || ! y) return x | y;

	if(rnd[x] > rnd[y]) { // 考虑 x,y 谁作为根,随机优先级大的作为根
		rs[x] = merge(rs[x], y); // x 为根,将 x 原先的右子树和以 y 为根的子树合并作为新的右子树
		psup(x);

		return x;
	}
	else  {
		ls[y] = merge(x, ls[y]); // 反之,将 y 原先的左子树和以 x 为根的子树合并作为新的左子树
		psup(y);

		return y;
	}
}
  • 注:根据笔者的写法,相当于是左儿子写右边,右儿子写左边的,不过无伤大雅。

扩展操作

insert

inline void insert(int p) {
	int x = 0, y = 0;

	split(root, p - 1, x, y);
	merge(merge(x, create(p)), y);
}

相当于将新增节点当一颗新树合并进去。

delete

inline void deleted(int p) {
	int x = 0, y = 0, z = 0;

	split(root, p, x, y);
	split(x, p - 1, x, z);

	z = merge(ls[z], rs[z]);
	root = merge(z, merge(x, y));

	return ;
}

分裂出只包含查询值 \(p\) 的平衡树,合并该树的左右儿子,则相当于丢掉根节点,等价于删去一个 \(p\) 元素。

标签:return,merge,int,void,Treap,split,FHQ,ls
From: https://www.cnblogs.com/endswitch/p/18667217

相关文章

  • 一种调试 线段树 / Treap / Splay / 左偏树 / LCT 等树形结构的技巧
    前言如果我们需要观察程序运行过程中,某一个变量、某一个序列的变化情况,你可以在修改的地方打断点debug,或者直接在需要的地方输出就行了。但是对于一些树形结构,我们不好将其直观地呈现出来,常常只是输出每一个结点的值,但是这就丢失了结点之间的连边情况。有时候不得不手动画图。......
  • FHQ-Treap
    \(FHQ-Treap\)是无旋平衡树的一种,码量相对少,并且简单易懂。一下简称\(treap\)(注意还有别的\(treap\),但是在本文中仅指\(FHQ-Treap\))。\(treap\)仅需要合并和分裂。\(treap\)结合了小根堆(父亲节点权值比儿子小)和二叉查找树(左子树的值比根小,右子树的值比根大)的特性。......
  • 学习笔记:旋转treap
    前言更好的阅读体验。无旋treap。默认读者会BST的基本操作、堆和旋转。本文旋转部分和上面那篇文章的相同。代码中是小根堆。思想treap既是一棵二叉查找树(tree),也是一个二叉堆(heap)。但是如果这两个数据结构用同一个权值维护,那么这两种数据结构是矛盾的。所以treap用......
  • 浅析FHQ-treap
    前言更好的阅读体验默认读者会BST的基本操作。节点定义替罪羊树采用了懒惰删除的方法,不会立即删除某个点,而是在重构时不放进数组。structnode{intch[2],val;intsiz1,siz2,cnt,sum;//扣去懒惰删除的节点数量,没扣去懒惰删除的节点数量,树内相同权......
  • FHQ-treap 学习笔记
    FHQ-Treap学习笔记範浩強之木,無旋之奇構,併合眸,妙用無窮;其當官也,避繁複之旋。其視心有二,分若離,合若聚,若星漢分合變幻,肖無跡矣。不用旋,巧避繁,古之所未有,今之所獨異。茲樹形奇,如天成,真算之妙。---------《算枢奇构》###基本操作众所周知,无旋treap不需要旋转,基本操作有两个,分......
  • FHQ- Treap学习笔记
    FHQ-Treap与Treap都保证在第一关键字有序的情况下,维护第二关键字以达到平衡的目的。但是Treap用的是旋转,FHQ-Treap用的是分裂和合并。FHQ-Treap与Treap不同的地方:优美的分裂和合并。非旋。支持区间修改FHQ-Treap与Treap相同的地方:都保证在第一关键字有序的情况......
  • 笔记:FHQ Treap 之三分裂
    小知识点,但是好像没什么人写,所以写一篇。在NOIP之前积攒一点rp。需要的知识平衡树(FHQTreap)前言一般在写FHQTreap的时候,都是按照某个值或排名\(k\),将Treap分成小于等于和大于\(k\)的两棵树,我们将其称为二分裂。那么,所谓三分裂,就是将Treap按照小于、等于、大于......
  • FHQ-treap模板
    可以再加一个struct把整个树封装起来。。跟oiwiki学的#include<bits/stdc++.h>usingnamespacestd;#include<bits/stdc++.h>usingnamespacestd;structNode{Node*ch[2];intval,prio,cnt,siz;Node(int_val):val(_val),cnt(1),siz(1){......
  • Treap学习笔记
    Treap(树堆)学习笔记(此处为带旋Treap)Treap简介Treap是一种二叉搜索树,其中,权值val满足二叉搜索树的性质,节点优先级priority满足堆的性质(作用后面会讲到)Treap适用情况因为属于二叉搜索树,所以可以维护二叉搜索树的信息,带旋Treap可以更好地控制树的深度,使得每次操作不至于被......
  • 「FHQ-Treap —— 码量最小的平衡树」学习笔记
    不同于普通Treap,FHQ-Treap不需要左旋和右旋操作来处理数据。因此FHQ-Treap也称作无旋Treap。FHQ-Treap是基于Split(分裂)和Merge(合并)两种操作的平衡树。其与普通Treap的原理完全不同。一些基础的操作:例如Insert(插入元素)和Delete(删除元素)。对于Insert(插入元素),新建一......