势能函数平衡树值域有交平衡树合并及复杂度证明
WZH 值域有交平衡树合并及复杂度证明
以下内容理论上对多种平衡树都成立,但是此处假设这个只是对 FHQ Treap 成立。
合并
对于两棵树 l,r ,设 l 树根的优先级大于 r ,那么先判断他们值域是否有交,如果没有交那么直接用 FHQ 的合并就行。如果有交就按照 l 的权值将 r 分裂后将 l 的两个儿子分别和分裂出来的子树合并。
例如如下代码:
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; }
|
若值域有 k 段交,则上述 merge 复杂度显然为 O(klogn) 。
复杂度证明
结论:对于多棵平衡树的合并,复杂度不超过 O(nlognlogV) 。
证明:
定义一颗平衡树 T 的势能 ϕ(T) 为:若平衡树所维护的数从小到大为 a1,a2,⋯,an ,则:
ϕ(T)=∑log(ai−ai−1)
那么多棵平衡树的总初始势能为 O(nlogV) 。
接下来证明两棵树 T1,T2 的合并会使势能减少 k−O(logV) 。
设 T1+T2→T 。
那么势能的变化量为 ϕ(T1)+ϕ(T2)−ϕ(T) 。
极端情况下 T1,T2 里面的每一段都只有一个数,那么不妨设这些数的距离分别为 d1,d2,⋯,dO(k) 。
那么 ϕ(T1)+ϕ(T2)=∑log(di+di+1) , ϕ(T)=∑log(di) 。
那么:
ϕ(T1)+ϕ(T2)−ϕ(T)=∑log(di+di+1)−∑log(di)=(∑log(di+di+1)−21log(di)−21log(di))−21log(d1)−21log(dm)=(∑log(22(di+di+1))−2log(di)+log(di+1))−O(logV)=(∑log(2)+log(2(di+di+1))−2log(di)+log(di+1))−O(logV)=klog(2)+(∑log(2(di+di+1))−2log(di)+log(di+1))−O(logV)
首先,以上推导过程只依赖于 log 而不依赖于其底数,所以我们不妨指定底数为 2 ,就有:
ϕ(T1)+ϕ(T2)−ϕ(T)=(∑log(2(di+di+1))−2log(di)+log(di+1))+k−O(logV)
其次, log 是一个上凸函数,那么 log 就满足不等式(忽略条件):
log(2a+b)≥2log(a)+log(b)
代入到上式中可得:
log(2(di+di+1))−2log(di)+log(di+1)≥0∑log(2(di+di+1))−2log(di)+log(di+1)≥0ϕ(T1)+ϕ(T2)−ϕ(T)≥k−O(logV)
那么每次合并两棵平衡树的时间复杂度为 O(klogn) ,且势能减少 k−O(logV) 。
那么就有:
∑kilogV≤O(nlogV)
∑ki≤O(nlogV)
∑kilogn≤O(nlognlogV)
于是时间复杂度得到了证明,为 O(nlognlogV) 。