平衡树

平衡树

这个东西就是来优化BST的,英文:treap
作用,插入查询,最大值最小值,前驱后继,排名
一个树的样子不优秀,所以我们需要进行旋转
不破坏BST的性质,来改变树的形态,从而达到平衡
满足BST性质并且中序遍历相同的BST 是不唯一的,这些BST都是等价的,所以我们可以在维护BST的基础上,通过改变BST上的形态是的每一个节点的左右子树大小达到平衡
改变形态并保持BST性质方法就是旋转,就是将儿子和父亲进行一个转换,但是不能破坏性质
1.儿子当成爸爸
2.调整儿子爸爸的左右子树,达到满足性质的树

void you(int &p)
{
	int q=a[p].l;//保存左儿子
	a[p].l=a[q].r,a[q].r=p;
	p=q;//其实就是一个交换的过程	
}

经过旋转,BST就变的平衡了,平衡树的思想就是利用随机来创造平衡条件,旋转的过程中必须得保持BST性质,所以我们每次插入新的节点时候都需要为维护BST性质,有点类似与堆,插入完必须维护一下BST性质
总体的说,平衡树通过恰当的旋转,既要满足BST性质,还要是的平衡,还得满足大根堆性质

splay

一个操作,很简单就是把一个节点旋转到根节点,或者其他的操作,其实就是一个循环旋转,直至到达目的
但是想象一下,如果一条链,无论怎么旋转,他还是一个链(危
所以我们把splay操作想简单了…
splay,双旋转,也就是两种旋转,时间复杂度O(n log n)分两种情况,

  • 1.有左儿子右儿子,先旋转左儿子,再旋转右儿子,
  • 2.之有右儿子,旋转两次右儿子
    例题1

文艺平衡树

给定序列以及若干次操作,每次把一个区间[l,r]左右翻转,所有操作后输出序列
嗯嗯嗯?
这道题,用splay来维护序列,构建二叉树的关键字不是元素,是下标!
如何取出一个区间[l,r]:将l-1旋转到根,然后将r+1旋转到根的右儿子,那么r+1
的左儿子就是所需的区间
然后用一个类似于lazy的标记方式来打一个翻转标记:交换左右子树
注意标记下传,应该在某一次splay之前将到它一路上所有点标记下传,
注意从根开始下传
例题2

LCT

把序列问题直接搬到了树上,同样我们需要把应用在序列上的数据结构搬到树上
LCT就是一个用splay动态维护树链剖分,也就是随心所用的想怎么剖就怎么剖
实边是确实有一条边相连,虚边是没有一条边链接
那么splay关键字就是节点的深度
注意,虚边这个点,是一个类似于单向边,你是我的父亲,但我不是你的儿子,父亲不认它当儿子
注意两个概念,一个是根节点,一个是树链顶部节点
所以判断关系的时候,不能判断父亲而判断儿子

acces

将点q到根的边全部变成实边(认儿子了),并且断开这条实边上其他的实边(包括链向儿子的)
于是我们会把根到q的一段路径拎出来,塞进一棵splay里面(也就是提出来一条链
然后从q开始每次splay到根,删掉右子树(将实边变成虚边,将这段链更深的部分),接上前一步操作的splay(链接一条实边),然后跳到更靠上的splay,直到根为止

makerroot

换根操作,将整个树的根换成点q
先acces q,我们发现,现在的根与q之间的实链在一个splay之间,q是一个最深的节点
如果把个根换成q,本质上就是把这条链直接翻转,所以只需要打一个翻转标记

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值