无旋treap学习小记

数据结构-Treap(树堆) 详解 Treap(树堆)是一种弱平衡的搜索树,与平衡树相同,Treap就是由Tree和Heap(树和堆)两种数据结构组合而成的数据结构。 Treap的每个节点上要额外储存一个值prioritypriority,代表每个节点的优先级。因此对于每个节点,不仅要满足二叉搜索树的基本性质,还需额外满足父节点的prioritypriority大于两个子节点的prioritypriority。实际上,这个prioriotypriorioty值又被称为"修正值"。 阅读详情

高一才学这么基本的平衡树,退役了~

鉴于旋转treap不能可持久化,与splay相比除了常数小以外没有什么不同,所以就不学了。


treap:

treap = tree + heap,即二叉搜索树+堆

它的中序遍历是有序的,这是二叉搜索树的性质。

且对于每一个点有一个随机的键值,对于整个树的任意一棵子树,键值满足堆的性质。

基于随机,树高期望是log的。

非持久化无旋treap:

核心操作有两个:
split和merge

即分离和合并。

split(x,k)表示把x为根的搜索树的前k个分离出来。

merge(a,b)表示合并以a为根和以b为根的搜索树。

注意b树的搜索树值一定要都在a树的右边才能用merge合并,不然就一定要一个个提出来插进去。

这两个操作只要有点智商都写得出来,只是优不优美的问题,标程放文章的最后。

可持久化treap:

注意到无论是split还是merge每次影响到的点都只有log个,且因为每次都是自上而下地遍历整棵树,所以这个是可以线段树一样可持久化的,写法会差不多。


注意treap中用到了随机,因为c++自带的rand()函数特别慢,所以一般手写。

真正实现的时候并不是给每个点一个键值,而是在merge的时候根据两棵子树的大小来加权再随机来决定谁在上面。

模板:

平衡树例题:
bzoj 3224: Tyvj 1728 普通平衡树

可持久化treap例题:
JZOJ 3658. 【NOI2014模拟】‘‘文本编辑器

T1:

#include<cstdio>
#define x0 t[x][0]
#define x1 t[x][1]
#define ul  unsigned long long
#define fo(i, x, y) for(int i = x; i <= y; i ++)
using namespace std;

const int N = 1e5 + 5;
const int inf = 2e9 + 1;

int n, op, x;
int rt, t[N][2], siz[N], c[2], z[N], td;

ul zz = 998244353; ul randx() {return zz *= 1000000007;}

void upd(int x) { siz[x] = siz[x0] + siz[x1] + 1;}
void split(int x, int k) {
	if(!x) return; c[0] = c[1] = 0;
	int z = siz[x0] < k;
	split(t[x][z], k - z * (siz[x0] + 1));
	t[x][z] = c[!z]; c[!z] = x; upd(x);
}
int merge(int a, int b) {
	if(!a || !b) return a + b;
	if(randx() % (siz[a] + siz[b]) < siz[a]) {
		t[a][1] = merge(t[a][1], b); upd(a); return a;
	} else {
		t[b][0] = merge(a, t[b][0]); upd(b); return b;
	}
}
int gr(int x, int k) {
	if(!x) return 0;
	if(z[x] >= k) return gr(x0, k);
	return gr(x1, k) + siz[x0] + 1;
}
void ins(int k) {
	z[++ td] = k; siz[td] = 1;
	split(rt, gr(rt, k));
	rt = merge(c[0], td); rt = merge(rt, c[1]);
}
void del(int k) {
	split(rt, gr(rt, k)); rt = c[0];
	split(c[1], 1); rt = merge(rt, c[1]);
}
int fi(int x, int k) {
	if(siz[x0] >= k) return fi(x0, k);
	if(siz[x0] + 1 == k) return z[x];
	return fi(x1, k - siz[x0] - 1);
}
int pre(int x, int k) {
	if(!x) return inf;
	if(z[x] < k) {
		int p = pre(x1, k);
		return p == inf ? z[x] : p;
	}
	return pre(x0, k);
}
int nxt(int x, int k) {
	if(!x) return inf;
	if(z[x] > k) {
		int p = nxt(x0, k);
		return p == inf ? z[x] : p;
	}
	return nxt(x1, k);
}

int main() {
	scanf("%d", &n);
	fo(i, 1, n) {
		scanf("%d %d", &op, &x);
		if(op == 1) ins(x);
		if(op == 2) del(x);
		if(op == 3) printf("%d\n", gr(rt, x) + 1);
		if(op == 4) printf("%d\n", fi(rt, x));
		if(op == 5) printf("%d\n", pre(rt, x));
		if(op == 6) printf("%d\n", nxt(rt, x));
	}
}

T2:

#include<bits/stdc++.h>
#define x0 t[x][0]
#define x1 t[x][1]
#define ll long long
#define ul unsigned long long
#define fo(i, x, y) for(int i = x; i <= y; i ++)
using namespace std;

const int N = 2e7;

int t[N][2], siz[N], rev[N], c[2], rt, tot, q, x, l, r, nw;
char v[N];

ul zz = 998244353;

ul randx() {return zz *= 1000000007;}

int xin(int &x) {
	if(!x) return 0;
	v[++ tot] = v[x]; siz[tot] = siz[x];
	t[tot][0] = x0; t[tot][1] = x1;
	rev[tot] = rev[x]; return x = tot;
}
void fan(int x) {swap(x0, x1), rev[x] ^= 1;}
void down(int x) {fan(xin(x0)), fan(xin(x1)), rev[x] = 0;}
void upd(int x) {if(x) siz[x] = siz[x0] + siz[x1] + 1;}
void split(int x, int k) {
	if(!x) return; c[0] = c[1] = nw = 0;
	if(rev[x]) down(x), nw = 1;
	int z = siz[x0] < k;
	split(nw ? t[x][z] : xin(t[x][z]), k - z * (siz[x0] + 1));
	t[x][z] = c[z ^ 1], c[z ^ 1] = x, upd(x);
}
int merge(int a, int b) {
	if(!a || !b) return a + b; nw = 0;
	if(randx() % (siz[a] + siz[b]) < siz[a]) {
		if(rev[a]) down(a), nw = 1;
		t[a][1] = merge(nw ? t[a][1] : xin(t[a][1]), b);
		upd(a); return a;
	} else {
		if(rev[b]) down(b), nw = 1;
		t[b][0] = merge(a, nw ? t[b][0] : xin(t[b][0]));
		upd(b); return b;
	}
}
void ins(int x, char p) {
	v[++ tot] = p, siz[tot] = 1; int y = tot;
	split(rt, x);
	rt = merge(c[0], y), rt = merge(rt, c[1]);
}
void del(int l, int r) {
	split(rt, l - 1); rt = c[0];
	split(c[1], r - l + 1);
	rt = merge(rt, c[1]);
}
void cpy(int l, int r, int x) {
	split(rt, l - 1); rt = c[0];
	split(c[1], r - l + 1); int p = c[0]; xin(p);
	rt = merge(rt, c[0]), rt = merge(rt, c[1]);
	split(rt, x);
	rt = merge(c[0], p), rt = merge(rt, c[1]);
}
void reverse(int l, int r) {
	split(rt, l - 1); rt = c[0];
	split(c[1], r - l + 1);
	fan(c[0]);
	rt = merge(rt, c[0]), rt = merge(rt, c[1]);
}
void query(int x) {
	split(rt, x - 1); rt = c[0];
	split(c[1], 1); putchar(v[c[0]]);
	rt = merge(rt, c[0]), rt = merge(rt, c[1]);
}

int main() {
	freopen("editor.in", "r", stdin);
	freopen("editor.out", "w", stdout);
	for(cin >> q; q; q --) {
		char ch[2]; scanf("%s", ch);
		if(ch[0] == 'I') {
			scanf("%d", &x); scanf("%s", ch);
			ins(x, ch[0]);
		}
		if(ch[0] == 'D') {
			scanf("%d %d", &l, &r);
			del(l, r);
		}
		if(ch[0] == 'C') {
			scanf("%d %d %d", &l, &r, &x);
			cpy(l, r, x);
		}
		if(ch[0] == 'R') {
			scanf("%d %d", &l, &r);
			reverse(l, r);
		}
		if(ch[0] == 'Q') {
			scanf("%d", &x);
			query(x);
		}
	}
}
【学习笔记】数据结构:无旋Treap 最近学习了一下无旋Treap,发现无旋Treap真的太好打了,而且也很好理解,很好用。 Treap? 什么是Treap? 顾名思义:Treap=Tree+heap,即“树堆”,“树”指的是二叉查找树,“堆”就是堆。 那二叉查找树跟堆有什么关系呢? 当输入的数据十分恶心的时候,普通的二叉查找树的时间复杂度就会由 nlog2nnlog_2nnlog2​n 退化到 n2n^2n2 级别,时间复杂度难以让人接受。 而我们现在考虑优化,我们可以在每一个节点上多放一个数,然后使得这棵树既满足二叉排序树的性质也满足堆的性 阅读详情

相关推荐

11.2.2 蓝桥杯树形数据结构之平衡树FHQ—Treap(无旋Treap)

无旋Treap是Treap(树堆)数据结构的一个变种,结合了二叉搜索树和堆的特性。与传统的Treap通过旋转操作保持平衡不同,无旋Treap通过分裂(Split)和合并(Merge)操作维护树的平衡,避免了复杂的旋转逻辑,从而得名“无旋”。无旋Treap结合了二叉搜索树和堆的优点,通过分裂和合并操作维持平衡,既简化了实现又保持了高效的性能。在蓝桥杯等算法竞赛中,掌握无旋Treap能够帮助参赛者高效解决一系列动态数据集合的问题,是学习数据结构和算法的重要内容。

tang7mj的博客 533

[C++ 学习笔记] FHQ-Treap (无旋 Treap)

C++ FHQ-Treap - 无旋 Treap - 树堆 学习笔记

lzl20220405的博客 3173

爬虫实战:抖音视频搜索数据爬虫开发实战(附完整Python源码)

【代码】抖音视频搜索数据爬虫开发实战(附完整Python源码)

weixin_61226361的博客 3598

无旋Treap(fhq)

对于任意节点,保证根左侧子树的所有节点比根小,右侧的所有节点比根大的树(没有相同节点),Treap只是利用堆的性质,赋予每一个节点一个随机值,按照随机值维护堆的形状,即在插入的情况中,如果树A的根节点的权重比树B的大,那树B就一定是树A的子树,再根据树B的根节点的值的大小确定是在树A的左子树还是右子树。合并就是将两个树合并成一棵树,其中x树上的全部值小于等于y树上的所有值,并且合并出来的树依然满足Treap的性质,具体逻辑可见下面的代码,文字不想写了。左右子树、值、权重、树的大小。

qq_43561934的博客 435

单粒子翻转对FPGA的影响及解决方法

单粒子翻转对FPGA的影响及解决方法

航天领域资深码农,型号经验丰富,一线干货分享 2446

LLaVA-1.5:多模态视觉问答新突破

LLaVA-1.5在多模态视觉问答(VQA)任务中取得了显著进展,主要得益于视觉-语言连接器的优化和特定任务数据集的增加。通过将连接器升级为两层MLP,模型在处理视觉与语言关系时表现更佳。同时,引入如OKVQA、OCRVQA等数据集,增强了模型在复杂视觉推理任务中的能力。在11个基准测试中,LLaVA-1.5超越了现有方法,展示了其强大的多模态能力。此外,模型通过提升输入图像分辨率、扩展语言模型和改进多语言能力,进一步提升了性能。尽管在短格式回答任务中初期表现不佳,但通过调整提示格式和微调,其性能显著提升

weixin_57060548的博客 945

平衡树中的神兵利器——非旋Treap(树堆)学习小记

前言   之前A组有一道题目,要你维护一个字符串的插一个字符、删一段字符、复制并粘贴一段字符、翻转一段字符、查询一个字符。我当然想到了splay。但是看了眼数据范围:字符串的总长度不超过231−1231−12^{31}-1,我就知道splay没戏,同时也很惊异这题连splay都切不了,那还能做吗?   于是我就打了暴力。   于是那题我至今未切。   大佬们估计都一眼看出是可持久化Trea...

qq_36551189的博客 526

企业级 Agent 在 K8s 上的运行模型

Kubernetes├── Agent Orchestrator(控制面)├── Agent Runtime Pods(执行面)├── Graph DSL(流程层)├── Tool Services(能力层)K8s(调度)+ Graph(流程)+ Agent(决策)+ Tool(执行)+ Guard(治理)

一起修行,不孤单。这里有编程语言、开发工具、学习方法论和踩坑笔记。用简单的话说复杂的事,陪你从小白到进阶。周更干货,欢迎一起成长! 1173

FHQ-Treap小记

写在前面 参考资料&&orz gyh 嘤 博主是在gyhgyhgyh大佬的博客的帮助下,学会了FHQ-Treap\text{FHQ-Treap}FHQ-Treap咋么写的,博文链接如下 Luckyblock—FHQ-Treap 感谢gyhgyhgyh大佬,gyhgyhgyh永远滴神! 另外的参考资料 Shiina_Mashiro—平衡树(Splay、fhq Treap) ctjcalc—【数据结构】FHQ Treap 详解 关于 FHQ-Treap\text{FHQ-Treap}FHQ-Tr

Loceaner的博客 3185

毕设助力!从0到1构建基于YOLO的家居安防异常活动监测系统,让你的毕设守护家庭安全

做完这个项目,你会发现自己完整走过了“数据采集→标注→模型训练→功能集成→界面开发”的毕设全流程,这不仅是技术能力的证明,更是对“技术守护生活”这一理念的实践。答辩时,你可以重点讲这几点:系统解决了家居安防的哪些痛点、对比了不同YOLO模型的性能差异、系统未来能怎么优化(比如对接智能门锁/报警器、实现语音交互)。未来,这个系统还能往“更智能”的方向发展:比如结合行为分析判断异常意图、开发移动端APP实现全屋设备联动、在智慧社区中实现多家庭联防……想象空间很大。

LXY_LOVE36的博客 125

五、MT8168 音频驱动之SPEAKER

本章主要讲解MT8168平台的内部SPEAKER驱动配置。分为HP接法和LINE OUT接法。2.1.3 audio_custom_exp.h设置。2.1.4 mixer_paths.xml设置。2.2.3 mixer_paths.xml设置。2.1.2 ProjectConfig 设置。2.2.2 ProjectConfig 设置。2.2.1 deconfig设置。2.1.1 DTS设置。......

Joon2020的博客 1664

非旋treap学习小记

说在前面 搁了很久的坑,终于遇到题目可以学一发。 听说这玩意除了LCT,几乎完爆同是维护平衡树的splay,好像LCT也可以用treap实现 Treap 顾名思义就是Tree+Heap,即树堆,既有二叉查找树的性质也有堆的性质,通常利用中序遍历的顺序和堆的高度为logloglog来解决许多问题,属于平衡树的一类。 本质上就是笛卡尔树,每个点有两个权值val,keyval,keyval,key,va...

sadnohappy 1702

【扣子AI开发】如何开发一个图像生成智能体?

【扣子AI开发】如何开发一个图像生成智能体,从创建到发布

tl437002770的博客 2427

「笔记」FHQ-Treap小记

写在前面 参考资料&&orz gyh 嘤 博主是在\(gyh\)大佬的博客的帮助下,学会了\(\text{FHQ-Treap}\)咋么写的,博文链接如下 Luckyblock—FHQ-Treap 感谢\(gyh\)大佬,\(gyh\)永远滴神! 另外的参考资料 Shiina_Mashiro—平衡树(Splay、fhq Treap) ctjcalc—【数据结构】FHQ Treap ...

Loceaner的博客 119

cartographer运行错误集合

播放bag的时候错误 Check failed: sensor_to_tracking->translation().norm() < 1e-5 The IMU frame must be colocated with the tracking frame. Transforming linear acceleration into the tracking frame will otherwise be imprecise tracking frame不是imu的link 修改lua文件中的.

Studying…… 2028

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

平衡树学习小记

总起修炼了2天,终于差不多完成基础了,数据结构都是很灵活的,不仅是应用,而且写代码也是有很多值得思考的地方。而在平衡树中,旋转是核心的核心。 先总结一下吧。先说明一些概念键值,所谓的key,我一般用val表示,就是当前点存的值。 ind(ex),引索,就是用平衡树要维护的东西,可能还用wei(ght)来表示。相当于普通序列中的下标。虚拟节点:第n+1个点,放在所有点之前,让平衡树有头;第n+2个

ZLTJohn的博客 1788

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

启发式合并(堆、set、splay、treap)/线段树合并学习小记

启发式合并 刚听到这个东西的时候,我是相当蒙圈的。特别是“启发式”这三个字莫名的装逼,因此之前一直没有学。 实际上,这个东西就是一个SB贪心。 以堆为例,若我们要合并两个堆a、b,我们有一种极其简单的做法:那就是比较一下它们的大小,将小的堆的每个元素依次插入到大的堆中。不妨设|a|≤|b||a|≤|b||a|≤|b|,则时间复杂度即为:O(|a|∗log2(|a|+|b|))O(|a|∗log...

qq_36551189的博客 2406

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

板子小记

  目前包含:多项式乘法+多项式求逆+多项式求ln+多项式求exp+多项式快速幂(跑得好慢啊QAQ) Code #pragma GCC optimize(3,&amp;amp;amp;amp;amp;amp;amp;quot;Ofast&amp;amp;amp;amp;amp;amp;amp;quot;,&amp;amp;amp;amp;amp;amp;amp;quot;inline&amp;amp;amp;amp;amp;amp;amp;quot;)

Ephemeral 655

平衡树 模板小记

平衡树(Balanced Binary Tree) 模板小记平衡树(Balanced~Binary~Tree)~模板小记平衡树(Balanced Binary Tree) 模板小记 基础概念:二叉搜索树(Binary Search Tree)(Binary~Search~Tree)(Binary Search Tree) 二叉树 leftchild<root<rightchildleftchi

绫 256

splay小记

学习了一下splay。splay主要就是干线段树干的活,外加区间翻转,插入删除,还有分裂合并。建树 就是普通的建成二叉树,为了方便以后的区间操作,会在两边建两个辅助的点。int build(int l,int r,int y) // [l,r],父亲是y { if(l > r) return 0; int mid = (l + r) / 2; int x = insert(

luotuoqingshan的博客 305

省选+NOI 第六部分 技巧与思想

分块 分块入门 分块入门_ACM败犬的博客-优快云博客 分块算法总结 分块算法总结_劭星の博客-优快云博客 数列分块入门(2019.8.15训练) 数列分块入门(2019.8.15训练)_nefu_ljw的博客-优快云博客 分块 分块_Lewis King的博客-优快云博客 分块——概述+例题1 分块——概述+例题1_蒟蒻柴犬首相的博客-优快云博客 UESTCACM 每周算法讲堂 分块 UESTCACM 每周算法讲堂 分块_哔哩哔哩_bilibili

青少年趣味编程 509

【BZOJ3224】普通平衡树

Description 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作: 1. 插入x数 2. 删除x数(若有多个相同的数,因只删除一个) 3. 查询x数的排名(若有多个相同的数,因输出最小的排名) 4. 查询排名为x的数 5. 求x的前驱(前驱定义为小于x,且最大的数) 6. 求x的后继(后继定义为大于x,且最小的数) Solution 这是一道练习

Facico的博客 1168

[WC2016]鏖战表达式

前言 题目的名称是:鏖(aˊo)(áo)(aˊo)战表达式。 题目 传送门 to UOJ 思路 去掉修改操作,我们怎么做?我第一次想到的是单调栈…… 使用 表达式树。这是一棵完满二叉树,满足如下条件: 每个节点是一个数字,或者一个操作符(运算符)。 中序遍历结果为原表达式。 将数字视为最大的优先级,则从优先级来说,父节点的优先级小于子节点的优先级。 举个栗子。看图! 第三条性质就是要保证:先...

七代目鸽影 496

【5.18 提高班小记】数据结构&&线性基

先挖坑: 1.fhq treap 2.左偏树(可持久化可并堆) 3.重量平衡树。 4.拟阵。 1 维护一个序列,支持: 1.单点修改。 2.区间翻转。 3.给定 [l,r],[l,r],[l,r], 执行 swap(ai,ai+1),&amp;amp;nbsp;swap(ai+2,ai+3)...swap(ai,ai+1),&amp;amp;nbsp;swap(ai+2,ai+3)...swap(a_i,a_{...

Hellsegamosken 359

浅谈无旋treap(fhq_treap)

一、简介 无旋Treap(fhq_treap),是一种不用旋转的treap,其代码复杂度不高,应用范围广(能代替普通treap和splay的所有功能),是一种极其强大的平衡树。 无旋Treap是一个叫做范浩强的大佬发明的(快%啊!) 在我们一起学习无旋Treap之前,本蒟蒻有几句活想说: 1.无旋Treap我个人认为是最容易理解的一种平衡树,而且编程复杂度不高,功能还那么强大。 ...

aaa3201的博客 1646

无旋treap学习笔记

无旋treap ,又称为 非旋treap , fhq_treap ,是一个非常实用的数据结构,用来优化一般的 二叉搜索树 所解决不了的问题,大大提高了时间的效率,在解决平衡树问题的应用较广。

White_gugu的博客 691
上一篇: 洛谷P3345 [ZJOI2015]幻想乡战略游戏
下一篇: bzoj 3489: A simple rmq problem
Cold_Chair
博客等级 码龄11年 158粉丝 410原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值