浅谈无旋treap(fhq_treap)

无旋Treap(fhq_treap)是一种不使用旋转操作的平衡树,由范浩强提出,具有编程复杂度低、功能强大的特点。它可以替代普通Treap和Splay,并且支持可持久化。本文介绍了无旋Treap与其他平衡树如AVL、普通Treap、Splay和红黑树的比较,强调无旋Treap的易理解和高效。核心操作包括merge和split,这两者使得无旋Treap实现无旋转平衡。文章还提供了一道模板题供读者实践。

一、简介

无旋Treap(fhq_treap),是一种不用旋转的treap,其代码复杂度不高,应用范围广(能代替普通treap和splay的所有功能),是一种极其强大的平衡树。

无旋Treap是一个叫做范浩强的大佬发明的(快%啊!)

在我们一起学习无旋Treap之前,本蒟蒻有几句活想说:

1.无旋Treap我个人认为是最容易理解的一种平衡树,而且编程复杂度不高,功能还那么强大。

 我一开始学平衡树的时候是先从普通的带旋转的Treap开始学的。那种Treap,我现在都没搞懂什么左旋右旋究竟是怎么一回事。

 我当时真的以为我这辈子都不指望学会平衡树了,直到djq大佬(快%!)告诉了我这种很美妙的数据结构。

 我真就不明白了,为什么那么多人愿意去学普通的Treap而不学无旋Treap。无旋Treap更容易理解,最主要的是他与普通的Treap相比能可持久化!(尽管我不会

 所以,在大家学习完无旋Treap以后,本蒟蒻请诸君不妨推广一下无旋Treap,造福更多的Oier。

 2.关于无旋Treap和其他平衡树的比较:(这个建议大家学完无旋Treap再来看,可能感触会更深刻一些)

  与AVL相比:旋转操作真的很浪费时间,最坏情况下复杂度为O(log n),而且AVL树难写无比,不适合运用于算法竞赛。

  与普通Treap相比:参见第一条

  与splay相比:基本上可以代替splay的所有功能,但是在处理LCT问题上没有splay优秀

  与rbt(红黑树相比):红黑树特别难写是众所周知的。

  与sbt相比:sbt是我认为的最强大的平衡树。但是无旋Treap中的merge、split操作的应用的广泛(可持久化Treap维护Hash之类的)是sbt做不到的。

二、Treap

  什么是Treap?

  Treap=Tree+heap

  相信大家都知道二叉堆吧。父节点的权值比子节点都要大(或小)

  而Treap,则是在BST(二叉查找树)的基础上,添加二叉堆中的这个元素。

  Treap与heap的区别是,heap是完全二叉树,而Treap不是。

  下面的

三、核心操作

我在前面说过,普通的Treap最烦人的地方便是旋转。

而无旋Treap是如何做到无旋的呢?

关键就在两个操作:merge和split

1.split

<
### FHQ Treap 实现区间查询功能 FHQ Treap 是一种基于分裂和合并操作的平衡树结构,能够高效地处理动态序列上的各种操作。为了实现区间查询功能,可以利用其高效的子树分割合并能力。 #### 节点定义 FHQ Treap 的基本节点除了存储键值外还需要额外的信息用于支持快速查询: ```cpp struct Node { int val, size; // 当前结点权值 和 子树大小 long long sum; // 维护当前区间的总和或其他聚合属性 Node *ch[2]; // 左右孩子指针 Node(int v):val(v),size(1),sum(v){ ch[0]=ch[1]=nullptr; } }; ``` #### 关键函数:Split 和 Merge - **Split** 函数按照给定的关键字 `k` 将一棵树分为两部分; - **Merge** 函数则将两个有序的部分重新组合成完整的树形结构[^1]。 通过上述两种基础变换,可以在 O(log n) 时间复杂度内完成任意位置的数据访问以及修改。 对于具体的区间求和问题,则需进一步扩展节点信息并调整相应逻辑: 当执行 Split 或者 Rotate 操作时同步更新涉及路径上各节点所携带的辅助字段 (如累加和),从而保证每次查询都能获得最新状态下的正确结果。 下面给出一段简单的 C++ 代码片段展示如何构建这样的数据结构及其核心方法: ```cpp // 合并两棵 fhq-treap 成为新的 fhq-treap Node* merge(Node *a, Node *b) { if (!a || !b) return a ? a : b; if ((rand() % (a->size + b->size)) < a->size) { a->push_down(); // 更新懒标记(如果有的话) a->ch[1] = merge(a->ch[1], b); a->pull_up(); return a; } else { b->push_down(); b->ch[0] = merge(a, b->ch[0]); b->pull_up(); return b; } } pair<Node*, Node*> split(Node *rt, int k) { if (!rt) return make_pair(nullptr, nullptr); rt->push_down(); pair<Node *, Node *> res; if (get_size(rt->ch[0]) >= k) { auto tmp = split(rt->ch[0], k); rt->ch[0] = tmp.second; rt->pull_up(); res.first = tmp.first; res.second = rt; } else { auto tmp = split(rt->ch[1], k-get_size(rt->ch[0])-1); rt->ch[1] = tmp.first; rt->pull_up(); res.first = rt; res.second = tmp.second; } return res; } ``` 以上实现了最基础版本的支持区间查询特性的 FHQ Treap 。实际应用中可能还需考虑更多细节优化性能表现,比如引入惰性传播机制减少不必要的计算开销等[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值