博文更新:
20190917 更新了一下merge和split函数的递归理解
定义:
无旋treap,就是不通过旋转的维护堆性质的treap,根本的原理还是 tree + heap。
与普通treap的不同之处:
大概就是可以可持久化。
然后区间操作的话,不知道有旋的行不行,用无旋的反正是比较好搞,区间操作举个例子就是让你把一段区间的数反过来等等。
现在听着可能区间操作什么的可能莫名其妙,反正学了无旋treap基操之后刷刷题就行了,现在先不要想区间操作了,我们先将基本操作。
先给例题:
本文建立在洛谷P3369上,共要实现6个功能:
1.插入一个数V
2.删除一个数V
3.找到V在树中的排名
4.找到树中排名为K的数是谁
5.找前驱
6.找后继
先讲无旋treap的灵魂操作:merge && split
merge:将两棵树x,y按照heap性质合并成一棵树,返回合并好的树的根节点
注意,有一个前提是y树中所有元素都比x树中大。
为什么要把两棵树合并?看下去才知道
怎么做到一开始y树所有节点值都比x树大?看了split你就懂了,现在只要在理解递归的时候牢牢记住这一点即可。
然后pri表示优先级,整体的思路是要递归理解。
自顶向下看的话,意思大概就是两棵树选择优先级更大的那个跟保留为当前根节点,比如说选择x树为当前根的话,x的左子树便已经与合并无瓜葛,因为y树所有元素都比x大,不可能连x的左儿子,因此接下去就是x的右树和y树的x右儿子争夺战。选择y作为当前根的思想是一样的
int merge(int x,int y){
if (!x || !y) return x+y;
if (pri[x] > pri[y]){
ch[x][1] = merge(ch[x][1],y);
return x;
}
else {
ch[y][0] = merge(x,ch[y][0]);
return y;
}
}