前言
眼看着联赛将近,周围的大佬们都开始学起了splay等高级数据结构算法,蒟蒻的我只好学一学treap,咦!?竟然有一种treap可以支持区间操作(splay)还那么友好码量适中?!小蒟蒻赶紧来安利一波
fhq_treap是一位名叫fhq的大佬想出来的(这不废话吗),它是基于treap的基础上加以优化得出的算法(这也是句废话),treap就是二叉搜索树加上堆,它每次进行一次操作(插入或删除等)都要经过左右旋转来维护二叉搜索树的平衡,每次都旋转一次好麻烦有木,于是乎,为了科技的创新偷懒fhq大佬创作出了这样一个算法,大大减少了代码复杂度,也让fhq_treap可以很轻易的完成区间上的操作!!造福(像我一样懒的~)人类呀
好我们来进入正题;
为什么fhq_treap能完成如此多的操作还码量适中呢? 一切都得益于两个神奇的操作 merge 和 split。 顾名思义,一个是将两颗treap树合并为一颗,一个是将一颗treap树分裂成两颗treap树。
1. merge
int merge(int x,int y){
if(!x || !y) return x+y;//如果有一颗为空,那么只要返回不为空的那一颗就行了
if(rd[x]<rd[y]){ //treap的做法,比较他们的优先值
ch[x][1]=merge(ch[x][1],y);
up(x);return x; // 将x的右子树与y合并为一颗,那么目前的x就是合并后的树
}
else{
ch[y][0]=merge(x,ch[y][0]);
up(y);return y;//反之亦然
}
}
2.split
void split(int now,int k,int &x,int &y){//意思是将now树,以k为分割点(大于k在右边,小于K在左边),分为x,y两棵树
if(!now) x=y=0;//如果now 树为空,那么x,y树都为空.
else{
if(val[now]<=k){
x=now,split(ch[now][1],k,ch[now][1],y);
}
else
y=now,split(ch[now][0],k,x,ch[now][0]);
up(now);
}
}
好了,两个基本操作讲完了,那么他有什么用?
以这两个操作为基础,就可以解决其他操作啦~
先看看插入
insert
int insert(int &root,int x){//原树是root,要插入x这个点
int a,b;
int v=val[x];
split(root,v,a,b);
root=marge(marge(a,x),b);
}
如果看不懂代码可以看看图。
这是一颗treap树,右边为要插入的点。

我们先把原树按要插入这个点的值分为两颗树

然后再要插入的点和小于他的那颗树连起来

最后只需将这颗树与大于他的这颗树连起来就行了

insert就讲完了。
继续挖坑以后有时间填