众所周知,堆式存储线段树空间要开到四倍,动态开点线段树空间要开到二倍。接下来给出证明。
动态开点线段树的空间大小只与线段树实际的节点数有关。一般开到 2 n 2n 2n。
静态线段树一般采用堆式存储,空间与最大节点编号有关。一般开到 4 n 4n 4n。
⌊ x + 1 2 ⌋ = ⌈ x 2 ⌉ \left\lfloor\frac {x+1}2\right\rfloor=\left\lceil\frac x2\right\rceil ⌊2x+1⌋=⌈2x⌉
显然。
⌊ x 2 ⌋ + ⌈ x 2 ⌉ = x \left\lfloor\frac {x}2\right\rfloor+\left\lceil\frac x2\right\rceil=x ⌊2x⌋+⌈2x⌉=x
显然。
节点 [ l , r ] ( l ≠ r ) , r − l + 1 = l e n [l,r](l\not=r),r-l+1=len [l,r](l=r),r−l+1=len的两个子节点分别为 [ l , ⌊ l + r 2 ⌋ ] , [ ⌊ l + r 2 ⌋ + 1 , r ] \left[l,\left\lfloor\frac{l+r}2\right\rfloor\right],\left[\left\lfloor\frac{l+r}2\right\rfloor+1,r\right] [l,⌊2l+r⌋],[⌊2l+r⌋+1,r],其宽度分别为: ⌈ l e n 2 ⌉ , ⌊ l e n 2 ⌋ \lceil\frac {len}2\rceil,\lfloor\frac{len}2\rfloor ⌈2len⌉,⌊2len⌋
其左区间宽度为:
⌊ l + r 2 ⌋ − l + 1 \left\lfloor\frac{l+r}2\right\rfloor-l+1 ⌊2l+r⌋−l+1
我们知道:
x − 1 < ⌊ x ⌋ ≤ x x-1<\lfloor x\rfloor \leq x x−1<⌊x⌋≤x
则:
l + r 2 − 1 < ⌊ l + r 2 ⌋ ≤ l + r 2 \frac {l+r}2-1<\left\lfloor\frac{l+r}2\right\rfloor\leq \frac{l+r}2 2l+r−1<⌊2l+r⌋≤2l+r
即:
r − l + 2 2 − 1 < ⌊ l + r 2 ⌋ − l + 1 ≤ r − l + 2 2 \frac {r-l+2}2-1<\left\lfloor\frac{l+r}2\right\rfloor-l+1\leq \frac{r-l+2}2 2r−l+2−1<⌊2l+r⌋−l+1≤2r−l+2
我们还知道:
r − l + 2 2 − 1 < ⌊ r − l + 2 2 ⌋ ≤ r − l + 2 2 \frac {r-l+2}2-1<\left\lfloor\frac{r-l+2}2\right\rfloor\leq \frac{r-l+2}2 2r−l+2−1<⌊2r−l+2⌋≤2r−l+2
在 ( r − l + 2 2 − 1 , r − l + 2 2 ] \left(\frac {r-l+2}2-1,\frac{r-l+2}2\right] (2r−l+2−1,2r−l+2]范围内显然只有一个整数,因此
⌊ l + r 2 ⌋ − l + 1 = ⌊ r − l + 2 2 ⌋ = ⌈ r − l + 1 2 ⌉ = ⌈ l e n 2 ⌉ \left\lfloor\frac{l+r}2\right\rfloor-l+1=\left\lfloor\frac{r-l+2}2\right\rfloor=\left\lceil\frac{r-l+1}2\right\rceil=\left\lceil\frac{len}2\right\rceil ⌊2l+r⌋−l+1=⌊2r−l+2⌋=⌈2r−l+1⌉=⌈2len⌉
同理我们可以得知右区间宽度为 l e n − ⌈ l e n 2 ⌉ = ⌊ l e n 2 ⌋ len-\left\lceil\frac{len}2\right\rceil=\lfloor\frac{len}2\rfloor len−⌈2len⌉=⌊2len⌋。
两个线段树。宽度相同则图形态完全相同(区分左右儿子)。
应用数学归纳法容易证明。
宽度为 2 k 2^k 2k的线段树是一颗满二叉树,它的节点数目为 2 k + 1 − 1 2^{k+1}-1 2k+1−1
首先我们考虑维护区间 [ 1 , n = 2 k ] [1,n=2^k] [1,n=2k]的线段树。
显然它的形态是满二叉树。
那它的节点数量为: ∑ k i = 0 2 i = 2 k + 1 − 1 \underset{i=0}{\overset {k}\sum}2^i=2^{k+1}-1 i=0∑k2i=2k+1−1
若 k = ⌈ log 2 n ⌉ k=\lceil\log_2 n\rceil k=⌈log2n⌉,则有:
⌊ n 2 ⌋ ≤ ⌊ 2 k 2 ⌋ \left\lfloor\frac n2\right\rfloor\leq\left\lfloor\frac {2^k}2\right\rfloor ⌊2n⌋≤⌊22k⌋
⌈ n 2 ⌉ ≤ ⌈ 2 k 2 ⌉ \left\lceil\frac n2\right\rceil\leq\left\lceil\frac {2^k}2\right\rceil ⌈2n⌉≤⌈22k⌉
显然。
线段树是一个Leafy Tree,即它的一个节点要么没有儿子,要么有左右儿子。
假设一个节点的宽度为 l e n = 1 len=1 len=1,那么它为叶子,若 l e n ≠ 1 len\not=1 len=1,则它有左右儿子。且根据3可知左右儿子宽度均不为 0 0 0。
假设根节点深度为 0 0 0,宽度为 n n n的线段树中一个深度为 k k k的节点的宽度等于所有下式中的至少一个:
( ∘ k i = 1 h i ) ( n ) = ( h 1 ∘ h 2 ∘ . . . ∘ h k ) ( n ) \left(\underset{i=1}{\overset k\circ}h_i\right)(n)=(h_1\circ h_2\circ ...\circ h_k )(n) (i=1∘khi)(n)=(h1∘h2∘...∘hk)(n)
其中 h i ∈ { f , g } , f ( x ≠ 1 ) = ⌊ x 2 ⌋ , g ( x ≠ 1 ) = ⌈ x 2 ⌉ h_i\in\{f,g\},f(x\not=1)=\lfloor\frac x2\rfloor,g(x\not=1)=\lceil\frac x2\rceil hi∈{f,g},f(x=1)=⌊2x⌋,g(x=1)=⌈2x⌉
应用归纳法显然。
( ∘ k i = 1 h i ) ( x ) ≤ g ( k ) ( y ) \left(\underset{i=1}{\overset k\circ}h_i\right)(x)\leq g^{(k)}(y) (i=1∘khi)(x)≤g(k)(y),其中 x ≤ y x\leq y x≤y
应用归纳法显然。
一颗宽度为 2 k 2^k 2k的线段树上一个深度为 x x x的节点的宽度可以表示为 2 k 2 x = ( ∘ x i = 1 h i ) ( 2 k ) \frac{2^k}{2^x}=\left(\underset{i=1}{\overset x\circ}h_i\right)(2^k) 2x2k=(i=1∘xhi)(2k),其中任意 h i h_i hi可以自由的取到 f / g f/g f/g
也就是说此节点宽度对应的 h h h序列为所有可能的长度为 x x x的 h h h序列。
也就说明此线段树上存在这样一个深度为 x x x的节点,是 2 k 2 x = ( ∘ x i = 1 h i ) ( 2 k ) \frac{2^k}{2^x}=\left(\underset{i=1}{\overset x\circ}h_i\right)(2^k) 2x2k=(i=1∘xhi)(2k)的必要条件。
这说明存在一组 h h h使得 2 k 2 x = ( ∘ x i = 1 h i ) ( 2 k ) \frac{2^k}{2^x}=\left(\underset{i=1}{\overset x\circ}h_i\right)(2^k) 2x2k=(i=1∘xhi)(2k)是此线段树上存在深度为 x x x的节点的充分条件。
应用归纳法显然。
一颗宽度为 n n n的线段树的图形态,是宽度为 2 k = ⌈ log 2 n ⌉ 2^{k=\lceil\log_2{n}\rceil} 2k=⌈log2n⌉的线段树图形态的一个包含根节点的生成树(根节点不变)。
这里指的不是同构,而是区分左右儿子方向的完全相同。
证明:
我们考虑线段树,宽度为 [ 1 , n ] [1,n] [1,n]。
假设线段树中必定存在叶子节点 x x x,其深度为 d > k d>k d>k。
假设存在这样的叶子节点,那我们知道 l e n x = ( ∘ d i = 1 h i ) ( n ) = 1 len_x=\left(\underset{i=1}{\overset d\circ}h_i\right)(n)=1 lenx=(i=1∘dhi)(n)=1
则: g ( d ) ( 2 k ) ≥ ( ∘ d i = 1 h i ) ( n ) = 1 g^{(d)}(2^k)\geq \left(\underset{i=1}{\overset d\circ}h_i\right)(n)=1 g(d)(2k)≥(i=1∘dhi)(n)=1
根据10,我们知道,这充分说明在宽度为 2 k 2^k 2k的线段树上存在一个节点其深度 > k >k >k,这显然是不可能的。因此矛盾。
这说明宽度为 n n n的线段树上没有任何一个节点的深度比宽度为 2 k 2^k 2k的线段树的节点的深度更大。而宽度为 2 k 2^k 2k的线段树是有 k + 1 k+1 k+1层节点的满二叉树,所以说明前者没有任何一个部分是后者没有的,因此得证。
由定理11可知:
宽度为 n n n的线段树的节点数,以及树高,均对应小于等于对应的 2 k 2^k 2k的线段树。
2 ⌈ log 2 n ⌉ < 2 n 2^{\lceil\log_2n\rceil}< 2n 2⌈log2n⌉<2n
证明:
2 ⌈ log 2 n ⌉ < 2 l o g 2 n + 1 = 2 n 2^{\lceil\log_2n\rceil}<2^{log_2n+1}=2n 2⌈log2n⌉<2log2n+1=2n
由5,12,13可知,动态开点线段树最多有 2 n − 1 2n-1 2n−1个节点,所以空间可以开到 2 n 2n 2n。
根节点、图形态和左右儿子方向完全相同的两颗二叉树,在堆式存储中占用的空间位置完全相同。
显然。
由定理15可知,我们只需要讨论宽度为 2 k = ⌈ log 2 n ⌉ 2^{k=\lceil\log_2n\rceil} 2k=⌈log2n⌉的满二叉树的节点编号的最大值即可。
显然这个最大编号为 2 k + 1 − 1 2^{k+1}-1 2k+1−1,即 < 4 n − 1 <4n-1 <4n−1。因此我们就知道了堆式存储二叉树的可能的节点编号最大值小于 4 n − 1 4n-1 4n−1。
原来证明这东西这么麻烦的。
是不是有什么简单方法。
如果您知道请您联系我。
仿照定理11,容易发现线段树去除了最后一层之后是一个满二叉树。
于是皆大欢喜。