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