Ynoi
2020-07-19 12:42:28
给你这样一个问题
有一个集合
操作有如下几种:
插入一个数,删除一个数,询问最大/最小值,询问一个数
如果看到这个问题,你一定会想到平衡树,时间复杂度
但是,如果说,每个数在一个值域范围
van♂树van Emde Boas 树就是这样一个数据结构,可以在
这个在
首先,如果在一个值域
一种方法是权值线段树,单次操作
还有一种是分块,首先我们把序列分成
大致如下
图:{
插入/删除 比较简单,只用修改一下
然后查询操作大概就是这样,以查前驱为例,首先在它所在的块查询,如果块内前面有
然后在这个块里找,找到块内最后面的一个
其他的查询操作也类似。
时间复杂度单次操作
不过我们考虑一下,块内找,以及在
那么我们是否可以用一样的方法继续处理下去呢,就是对分块继续分块?
这就是vEB树的思想!
就像这样
好,现在对于vEB树,我们现在就有下面一个结构:
定义
基础结构是
如果大小大于
max,min存储vEB树中最大和最小的数,如果没有用
一般情况下为了方便,我们设置
然后是很重要的一点,就是
大概就是这样
好,现在我们开始操作。
直接返回root的max/min即可
比如说,我们现在要插入这么一个位置
那么现在有这么几种情况
(此时max/min都不存在)
那么我们直接把max和min赋值成这个数即可
然后由于summary会被修改,所以我们就递归到summary继续修改即可
由于min并不存在于cluster中,所以我们就没必要在cluster递归下去
现在有这么两种情况
如果说,这个数
如果
如果说
然后我们分析一下时间复杂度,每次递归下去的话,规模就会变成原来的根号。
那么我们假设
那么,这里我们也可以回答,为什么min往下存会错了。
假如一个空的位置,那么同一个点的
单次查询复杂度 相当于是
这应该是vEB树里最复杂的一个了
假设我们删除如下位置的数
假如这个块只有一个数的话(max = min),那么直接把max和min设为不存在即可。然后由于summary修改了,所以我们只往summary递归下去就可以了。
假如这个块有多个数,下面分这么几种情况:
第一种,删的既不是max也不是min
没什么好说的,递归下去。
第二种,删的是
现在相当于是把子块中的最小删掉了(因为min不在cluster中),并查询删完之后的最小值。
就像这样
但是子块的最小值我们不能直接知道。
不过我们可以先用A块的
然后我们可以往
同时我们必须更新A块的
一样,我们再用A块的
第三中,删
和删
复杂度分析
和插入一样
以求后继为例
现在我们求红箭头所指的位置的后继
现在有两种情况
1.后继在块内(用
那么递归下去即可
查询前驱的话也类似,不过有个特点就是如果递归下去发现查不到前驱,那么它的前驱就是
2.后继不在块内
这个相当于先求出B后面的第一个块,使得这个块内有数,那么答案就是这个块的
那么怎么找到这个块?
就是在
那么递归下去即可
找前驱在这里就完全对称了。
复杂度分析:
一样,每递归一层规模变为原来的根号