值域有交平衡树合并及复杂度证明

值域有交平衡树合并及复杂度证明

以下内容理论上对多种平衡树都成立,但是此处假设这个只是对 FHQ Treap 成立。

合并

对于两棵树 l,rl,r ,设 ll 树根的优先级大于 rr ,那么先判断他们值域是否有交,如果没有交那么直接用 FHQ 的合并就行。如果有交就按照 ll 的权值将 rr 分裂后将 ll 的两个儿子分别和分裂出来的子树合并。

例如如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
void split(int p,int x,int &l,int &r){
if(!p)return (void)(l=r=0);
down(p);
if(val[p]<=x){
l=p;
split(son[p][1],x,son[p][1],r);
}
else{
r=p;
split(son[p][0],x,l,son[p][0]);
}
relax(p);
up(p);
}
int getmin(int p){
while(son[p][0])down(p),p=son[p][0];
return val[p];
}
int getmax(int p){
while(son[p][1])down(p),p=son[p][1];
return val[p];
}
int Merge(int l,int r){
if(!l||!r)return l+r;
if(dat[l]>dat[r]){
down(l);
son[l][1]=Merge(son[l][1],r);
up(l);
relax(l);
return l;
}
else{
down(r);
son[r][0]=Merge(l,son[r][0]);
up(r);
relax(r);
return r;
}
}
int merge(int l,int r){
if(!l||!r)return l+r;
down(l);down(r);
if(getmax(l)<=getmin(r))return Merge(l,r);
if(getmax(r)<=getmin(l))return Merge(r,l);
if(dat[l]<dat[r])swap(l,r);
int x,y;
split(r,val[l],x,y);
son[l][0]=merge(son[l][0],x);
son[l][1]=merge(son[l][1],y);
relax(l);
up(l);
return l;
}

若值域有 kk 段交,则上述 merge 复杂度显然为 O(klogn)O(k\log n)

复杂度证明

结论:对于多棵平衡树的合并,复杂度不超过 O(nlognlogV)O(n\log n\log V)

证明:

定义一颗平衡树 TT 的势能 ϕ(T)\phi(T) 为:若平衡树所维护的数从小到大为 a1,a2,,ana_1,a_2,\cdots,a_n ,则:

ϕ(T)=log(aiai1)\phi(T)=\sum \log(a_{i}-a_{i-1})

那么多棵平衡树的总初始势能为 O(nlogV)O(n\log V)

接下来证明两棵树 T1,T2T_1,T_2 的合并会使势能减少 kO(logV)k-O(\log V)

T1+T2TT_1+T_2\to T

那么势能的变化量为 ϕ(T1)+ϕ(T2)ϕ(T)\phi(T_1)+\phi(T_2)-\phi(T)

极端情况下 T1,T2T_1,T_2 里面的每一段都只有一个数,那么不妨设这些数的距离分别为 d1,d2,,dO(k)d_1,d_2,\cdots,d_{O(k)}

那么 ϕ(T1)+ϕ(T2)=log(di+di+1)\phi(T_1)+\phi(T_2)=\displaystyle\sum \log(d_i+d_{i+1})ϕ(T)=log(di)\phi(T)=\displaystyle\sum \log(d_i)

那么:

ϕ(T1)+ϕ(T2)ϕ(T)=log(di+di+1)log(di)=(log(di+di+1)12log(di)12log(di))12log(d1)12log(dm)=(log(2(di+di+1)2)log(di)+log(di+1)2)O(logV)=(log(2)+log((di+di+1)2)log(di)+log(di+1)2)O(logV)=klog(2)+(log((di+di+1)2)log(di)+log(di+1)2)O(logV)\begin{aligned} \phi(T_1)+\phi(T_2)-\phi(T) &= \displaystyle\sum \log(d_i+d_{i+1})-\displaystyle\sum \log(d_i) \\ &=(\displaystyle\sum \log(d_i+d_{i+1})-\frac{1}{2}\log(d_i)-\frac{1}{2}\log(d_i))-\frac{1}{2}\log(d_1)-\frac{1}{2}\log(d_m) \\ &=(\displaystyle\sum \log(\frac{2(d_i+d_{i+1})}{2})-\frac{\log(d_i)+\log(d_{i+1})}{2})-O(\log V)\\ &=(\displaystyle\sum \log(2)+\log(\frac{(d_i+d_{i+1})}{2})-\frac{\log(d_i)+\log(d_{i+1})}{2})-O(\log V)\\ &=k\log(2)+(\displaystyle\sum \log(\frac{(d_i+d_{i+1})}{2})-\frac{\log(d_i)+\log(d_{i+1})}{2})-O(\log V) \end{aligned}

首先,以上推导过程只依赖于 log\log 而不依赖于其底数,所以我们不妨指定底数为 22 ,就有:

ϕ(T1)+ϕ(T2)ϕ(T)=(log((di+di+1)2)log(di)+log(di+1)2)+kO(logV)\phi(T_1)+\phi(T_2)-\phi(T)=(\displaystyle\sum \log(\frac{(d_i+d_{i+1})}{2})-\frac{\log(d_i)+\log(d_{i+1})}{2})+k-O(\log V)

其次, log\log 是一个上凸函数,那么 log\log 就满足不等式(忽略条件):

log(a+b2)log(a)+log(b)2\log(\frac{a+b}{2})\ge\frac{\log(a)+\log(b)}{2}

代入到上式中可得:

log((di+di+1)2)log(di)+log(di+1)20log((di+di+1)2)log(di)+log(di+1)20ϕ(T1)+ϕ(T2)ϕ(T)kO(logV)\log(\frac{(d_i+d_{i+1})}{2})-\frac{\log(d_i)+\log(d_{i+1})}{2}\ge 0 \\ \displaystyle\sum \log(\frac{(d_i+d_{i+1})}{2})-\frac{\log(d_i)+\log(d_{i+1})}{2}\ge 0\\ \phi(T_1)+\phi(T_2)-\phi(T)\ge k-O(\log V)

那么每次合并两棵平衡树的时间复杂度为 O(klogn)O(k\log n) ,且势能减少 kO(logV)k-O(\log V)

那么就有:

kilogVO(nlogV)\sum k_i\log V\le O(n\log V)

kiO(nlogV)\sum k_i \le O(n\log V)

kilognO(nlognlogV)\sum k_i\log n \le O(n\log n\log V)

于是时间复杂度得到了证明,为 O(nlognlogV)O(n\log n\log V)