无旋转Treap是一个神奇的数据结构,能够支持插入,删除,查询k大,查询某个数的排名,查询前驱后继,支持各种区间操作和持久化.基于旋转的Treap无法实现区间反转等操作,但是无旋Treap可以轻易地支持区间操作.那为什么区间操作不用Splay而要去学无旋转Treap?原因很简单,Splay的时间复杂度是均摊的不能可持久化,而且无旋转Treap的代码量少得起飞(明明是yyf的Splay太丑了),而且无旋转Treap不容易写(翻)挂(车). 从这里开始 节点 分裂和合并 插入与删除 其他操作 建树…
最近在研究平衡树,看起来这种东西又丧水又很深,感觉很难搞清楚.在Ditoly学长的建议下,我先学习了正常的treap,个人感觉这应该是平衡树当中比较好懂的而且比较好写的一种. 然而,发现带旋treap有很多无法支持的操作,例如各种区间操作,而且由于会旋转无法可持久化,这是一个十分影响实用性的问题,在没有办法支持区间操作的情况下,我有2种选择: 1)滚去学splay:2)学习无旋treap 正常人应该都会去学习splay,然而我选择了后者,因为貌似splay在FJ省选R2T1中被卡成傻逼了....…
此为平衡树系列第二道:文艺平衡树您需要写一种数据结构,来维护一个有序数列,其中需要提供以下操作: 翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1 输入 第一行为n,m n表示初始序列有n个数,这个序列依次是(1,2……n-1,n) m表示翻转操作次数接下来m行每行两个数[l,r] 数据保证 1<=l<=r<=n 输出 输出一行n个数字,表示原始序列经过m次变换后的结果 样例输入 5 3 1 3 1 3 1 4 样例输出 4 3 2 1…
题目: 此为平衡树系列第一道:普通平衡树您需要写一种数据结构,来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个)3. 查询x数的排名(若有多个相同的数,因输出最小的排名)4. 查询排名为x的数5. 求x的前驱(前驱定义为小于x,且最大的数)6. 求x的后继(后继定义为大于x,且最小的数) n<=100000 所有数字均在-107到107内. 输入样例: 10 1 106465 4 1 1 317721 1 460929 1 644985 1 841…
题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=3224 https://www.luogu.org/problemnew/show/P3369 Description 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个)3. 查询x数的排名(若有多个相同的数,因输出最小的排名)4. 查询排名为x的数5. 求x的前驱(前驱定义为小于x,且最大的数)6…
3223: Tyvj 1729 文艺平衡树 Time Limit: 10 Sec  Memory Limit: 128 MB Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1 Input 第一行为n,m n表示初始序列有n个数,这个序列依次是(1,2……n-1,n)  m表示翻转操作次数接下来m行每行两个数[l,r] 数据保证 1<=l<…
题面 维护一个序列,支持以下操作: 1.在某个位置插入一段值连续的数. 2.删除在当前序列位置连续的一段数. 3.查询某个位置的数是多少. 题解 显然平衡树,一个点维护一段值连续的数,如果插入或者删除操作需要分裂这个点,就直接分裂.每次插入最多只会分裂1个点,每次删除最多分裂2个点,所以时间复杂度是O(nlogn)O(nlogn)O(nlogn)的. 我写的无旋treap. CODE #include <bits/stdc++.h> using namespace std; inline vo…
国际惯例的题面:这种维护排序序列,严格大于的进行操作的题都很套路......我们按照[0,k],(k,2k],(2k,inf)分类讨论一下就好.显然第一个区间的不会变化,第二个区间的会被平移进第一个区间,第三个区间的相对大小不会变化.于是我们直接把第二个区间拆了重构,一个一个插入第一个区间即可.因为每次这样做最少减半,所以每个元素只会被重构log次,复杂度nlog^2n.这种按照值域分离区间的操作,非旋转treap实现起来是最简单的......然而第一次写非旋转treap还是出了一点问题,注意它…
普通的Treap模板 今天自己实现成功 /* * @Author: chenkexing * @Date: 2019-08-02 20:30:39 * @Last Modified by: chenkexing * @Last Modified time: 2019-08-02 22:33:17 */ // #pragma GCC optimize(2) // #pragma GCC optimize(3) // #pragma GCC optimize(4) #include <algorit…
一开始光知道pushdown却忘了pushup......... #include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<queue> #define MAXN 100010 using namespace std; inline int read() { ; char ch=getchar(); ')ch=getchar(); ') { s…
转载自ZZH大佬,原文:http://www.cnblogs.com/LadyLex/p/7182491.html 今天我们来学习一种新的数据结构:无旋treap.它和splay一样支持区间操作,和treap一样简单易懂,同时还支持可持久化. 无旋treap的节点定义和treap一样,都要同时满足树性质和堆性质,我们还是用rand()来实现平衡 而无旋treap与treap不同的地方,也是其核心,就是它不旋转用两个新的核心函数:merge函数(合并两棵子树)和split函数(分裂出某棵树的前k个…
今天我们来学习一种新的数据结构:无旋treap.它和splay一样支持区间操作,和treap一样简单易懂,同时还支持可持久化. 无旋treap的节点定义和treap一样,都要同时满足树性质和堆性质,我们还是用rand()来实现平衡 而无旋treap与treap不同的地方,也是其核心,就是它不旋转用两个新的核心函数:merge函数(合并两棵子树)和split函数(分裂出某棵树的前k个节点,并且作为一棵树返回) 首先看merge函数,它是一个递归实现的过程,先看代码: Treap *merge(Tr…
!前置技能&概念! 二叉搜索树 一棵二叉树,对于任意子树,满足左子树中的任意节点对应元素小于根的对应元素,右子树中的任意节点对应元素大于根对应元素.换言之,就是满足中序遍历为依次访问节点对应元素为升序的二叉树. 平衡树 一棵二叉搜索树,为了防止插入.查询等在朴素二叉搜索树中复杂度为$O(Dep)$的操作在极端数据下会$TLE$,而在操作中不断通过旋转等操作使得树的形态更加平衡,并满足中序遍历不变. $Treap$ 一棵基于给每个点随机分配权值并维护堆结构以保持树结构较为平均的平衡树 无旋$Tre…
题目: 此为平衡树系列第一道:普通平衡树您需要写一种数据结构,来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个)3. 查询x数的排名(若有多个相同的数,因输出最小的排名)4. 查询排名为x的数5. 求x的前驱(前驱定义为小于x,且最大的数)6. 求x的后继(后继定义为大于x,且最小的数) n<=100000 所有数字均在-107到107内. 输入样例: 10 1 106465 4 1 1 317721 1 460929 1 644985 1 841…
在刷了许多道平衡树的题之后,对平衡树有了较为深入的理解,在这里和大家分享一下,希望对大家学习平衡树能有帮助. 平衡树有好多种,比如treap,splay,红黑树,STL中的set.在这里只介绍几种常用的:treap.splay和替罪羊树(其中treap包括旋转treap和非旋转treap). 一.treap treap这个词是由tree和heap组合而成,意思是树上的的堆(其实就是字面意思啦qwq).treap可以说是由二叉搜索树(BST)进化而来,二叉搜索树每个点满足它左子树中所有点权值都比它…
3224: Tyvj 1728 普通平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 20328  Solved: 8979[Submit][Status][Discuss] Description 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个)3. 查询x数的排名(若有多个相同的数,因输出最小的排名)4. 查询排名为x的数5. 求x的前驱(前驱定义为…
直接上代码 正所谓 人傻自带大常数 平衡树的几种姿势:  AVL Red&Black_Tree 码量爆炸,不常用:SBT 出于各种原因,不常用. 常用: Treap 旋转 基于旋转操作和随机数堆 但不支持区间操作. 非旋转 基于随机数堆和拆分合并操作 常数较大 时间复杂度:很难被卡,均摊O(logN) #include<cstdio> #include<iostream> #include<cstdlib> #define MAXN 100005 using n…
二逼平衡树 bzoj-3196 Tyvj-1730 题目大意:请写出一个维护序列的数据结构支持:查询给定权值排名:查询区间k小值:单点修改:查询区间内定值前驱:查询区间内定值后继. 注释:$1\le n,m\le 5\times 10^4$. 想法: 在这里给予三种题解: 1)首先,最容易想到的应该就是树状数组套主席树也就是常说的带修改主席树. 第一个操作是简单的,我们只需要提取出当前区间的权值线段树后在上面二分即可. 第二个操作是主席树的看家本领好伐 第三个操作就是待修改主席树的意义.我们利用…
有可能当树中有键值相同的节点时,貌似是要对Split和Merge均进行复制的,本人实测:只在Split的时候复制得到了一个WA,但只在Merge的时候复制还是AC,可能是恰好又躲过去了.有人说假如确保键值唯一,或者在一个节点保存相同键值的多个点的实现,则只需要在其中一个进行复制,因为从根到达叶子的路径是唯一的,但假如有多个点,分裂操作把这些权值相同的点分成两部分,而在插入/删除节点之后有可能会使得一棵树的形态改变(基于随机优先级),这些权值相同的点未必是Split时复制出来的那几个.暂时没有想明…
题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3223 平衡树处理区间问题的入门题目,普通平衡树那道题在维护平衡树上是以每个数的值作为维护的标准,而处理区间问题时,维护平衡树的应该是每个位置的下标,所以平衡树中序遍历时应该是当前区间的样子.例如: {1 2 3 4 5}翻转区间1 3,则中序遍历应该输出{3,2,1,4,5}. 提供splay和无旋Treap的题解. splay做法: #include<bits/stdc++.h>…
题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3224 平衡树入门题,学习学习. splay(学习yyb巨佬) #include<bits/stdc++.h> using namespace std; typedef long long ll; ; const int INF = 1e9; inline void read(int &n) { register , t = ; register char ch = getch…
题目描述 某一天gty在与他的妹子玩游戏.妹子提出一个游戏,给定一棵有根树,每个节点有一些石子,每次可以将不多于L的石子移动到父节点,询问将某个节点的子树中的石子移动到这个节点先手是否有必胜策略.gty很快计算出了策略.但gty的妹子十分机智,她决定修改某个节点的石子或加入某个新节点.gty不忍心打击妹子,所以他将这个问题交给了你.另外由于gty十分绅士,所以他将先手让给了妹子. 输入 第一行两个数字,n和L,n<=5*10^4,L<=10^9第二行n个数字,表示每个节点初始石子数.接下来n-…
题目描述 维护一个队列,初始为空.依次加入 n(1≤n≤105)个数 ai(-109≤ai≤109),第 i(1≤i≤n)个数加入到当前序列第 bi(0≤bi≤当前序列长度)个数后面.输出最终队列. 输入格式 输入包含一个数 n(1≤n≤3×105),表示最终序列长度. 接下来 n 行,每行两个数 ai,bi,表示把 ai 放在当前序列第 bi 个数后面. 输出格式 输出 n 行,每行一个数,表示最终序列. 样例数据 1 输入 5 1 0 2 0 3 0 4 0 5 0 输出 5 4 3 2 1…
题目链接 splay: #include<bits/stdc++.h> using namespace std; typedef long long ll; ,inf=0x3f3f3f3f; ],val[N],siz[N],rev[N],tot,n,m,a[N],rt; ,ch[u][]=ch[u][]=rev[u]=; return u;} ]]+siz[ch[u][]]+;} ,swap(ch[u][],ch[u][]),rev[ch[u][]]^=,rev[ch[u][]]^=;} vo…
https://www.luogu.org/problem/P3391 使用无旋Treap维护序列,注意的是按顺序插入的序列,所以Insert实际上简化成直接root和Merge合并,但是假如要在序列中插入某个数,则要SplitRank到正确的位置. 注意SplitRank的写法以及Pushdown的东西. #include<bits/stdc++.h> using namespace std; typedef long long ll; #define ls(p) ch[p][0] #def…
因为学了treap,不想弃坑去学splay,终于理解了无旋treap... 好像普通treap没卵用...(再次大雾) 简单说一下思想免得以后忘记.普通treap因为带旋转操作似乎没卵用,而无旋treap可以不旋转. 经典地不能再经典的例题   题目描述 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作: 插入x数 删除x数(若有多个相同的数,因只删除一个) 查询x数的排名(若有多个相同的数,因输出最小的排名) 查询排名为x的数 求x的前驱(前驱定义为小于x,且最大的数…
一.简介 无旋Treap(fhq_treap),是一种不用旋转的treap,其代码复杂度不高,应用范围广(能代替普通treap和splay的所有功能),是一种极其强大的平衡树. 无旋Treap是一个叫做范浩强的大佬发明的(快%啊!) 在我们一起学习无旋Treap之前,本蒟蒻有几句活想说: 1.无旋Treap我个人认为是最容易理解的一种平衡树,而且编程复杂度不高,功能还那么强大. 我一开始学平衡树的时候是先从普通的带旋转的Treap开始学的.那种Treap,我现在都没搞懂什么左旋右旋究竟是怎么一回…
Treap——大名鼎鼎的随机二叉查找树,以优异的性能和简单的实现在OIer们中广泛流传. 这篇blog介绍一种不需要旋转操作来维护的Treap,即无旋Treap,也称Fhq-Treap. 它的巧妙之处在于只需要分离和合并两种基本操作,就能实现任意的平衡树常用修改操作. 而不需要旋转的特性也使编写代码时不需要考虑多种情况和复杂的父亲儿子关系的更新,同时降低了时间复杂度. 此外,它还可以方便地支持可持久化,实在是功能强大. 接下来系统性地介绍一下无旋Treap的原理和实现,最后讲解一下应用和例题.…
非旋转Treap:用运行时间换调试时间的有效手段   Hello大家好,我们今天来聊一聊非旋转Treap. 相信各位或多或少都做过些序列上的问题.如果水题我们考虑暴力:不强制在线我们可能用过莫队和待修改莫队:不更改序列上的时间戳信息的我们使用线段树或者树状数组,也有可能请出主席树.那如果更大幅度的操作,我们要用到splay或者块链.但是!我们今天介绍一种特殊的平衡树,用时间换取时间的数据结构. 啥意思?如果写过splay和块链,前者的调试时间和后者的敲版子时间让我们头痛欲裂,但是这个平衡树,好写…
刚刚跟着EM-LGH大佬学了非旋转Treap 非常庆幸不用再写万恶的rotate了(来自高级数据结构的恶意) 来记一下 Treap 概念 简单来说,\(Tree_{二叉搜索树} * Heap_堆 = Treap_{平衡树}\) 这显然不是袁隆平爷爷干的 二叉搜索树,堆←不懂请戳这里 显然这两样东西有各自的排列顺序--左小右大以及根小(大)儿子大(小) 对于寻找答案来讲,二叉搜索树更加方便 - 那么堆用来干嘛呢 很简单,用来达到期望平衡 - 怎么实现呢 通过另一个关键字 - 为什么是"期望&quo…