treap(树堆)
是在二叉搜索树的基础上,通过维护随机附加域,使其满足堆性质,从而使树相对平衡的二叉树;
为什么可以这样呢?
因为在维护堆的时候可以同时保证搜索树的性质;
(比如当一棵树的一个域满足堆的性质时,只要不断的互换左右,她的另一个域总会满足搜索树的性质)
(当一棵树的一个域满足搜索树的性质时,只要不断的上下旋转,她的另一个域总会满足二叉堆的性质)
于是树堆有两种实现:
旋转treap:
她的操作基于旋转;
注意:当存在相同val时,对于旋转treap,是存在一个节点中的;
roll(旋转操作)
交换点x与她的x.ch(i):
fa(x).ch(i)=x.ch(i);
x.ch(i)=x.ch(i).ch(i^1);
x.ch(i).ch(i^1)=x;
以上操作是一个改变上下位置却不影响搜索树性质的方法,与splay类似;
1 void roll(int &now){ 2 int wh=data[data[now].ch[0]].key<data[data[now].ch[1]].key?0:1; 3 int son=data[now].ch[wh]; 4 data[now].ch[wh]=data[son].ch[wh^1]; 5 data[son].ch[wh^1]=now; 6 up(now); 7 now=son; 8 }