跳到主要内容

线段树:开多大?

本文研究线段树的空间问题。

注意: 虽然下面给出了 “空间复杂度”,但是不要按空间复杂度开!要按照 “总结点不超过” 开。下面把需要开的大小记作 TT

普通线段树

假设线段树需要维护区间 [1,n][1,n]

结论:T=4nT=4n

也就是一共有 nn 个叶子结点,最好情况下深度为 log2n+1\log_2n+1,最坏情况下深度为 log2n+2\log_2n+2

所以总结点不超过 2log2n+2=4n2^{\log_2n+2}=4n,空间复杂度是 O(n)O(n)

动态开点线段树

假设线段树需要维护区间 [1,n][1,n],一共要处理 mm 次更新。 结论:T<40mT\lt40m

最坏情况下深度为 log2n+2\log_2n+2,也就是每次更新最多创建 log2n+2\log_2n+2 个节点,总结点不超过 mlog2n+2mm\log_2n+2m,空间复杂度是 O(mlog2n)O(m\log_2n)

然而计算 log\log 太麻烦了,我们尝试线性近似:

  • 假设 mlog2n+2mkmm\log_2n+2m\le km,待定 kk

  • 两边约去 mm,得 log2n+2k\log_2n+2\le k,左边肯定是单调递增的,代入 n=1011n=10^{11}log21011+238.54\log_210^{11}+2\approx38.54,稍微取整一下,取 k=40k=40

    (一般也不太可能遇到 >1011\gt10^{11} 数量级的数据了吧......)

类似地,我们得到下表。32m32m40m40m 是常见的取值,别的看个乐就好。

nn\le10510^510910^{9}__int32 上界)101110^{11}101210^{12}101910^{19}__int64 上界)
空间估算(节点)<20m\lt20m<32m\lt32m, m<<5<40m\lt40m(m<<5)+(m<<3)<42m\lt42m<66m\lt66m

可持久化线段树

假设线段树需要维护区间 [1,n][1,n],一共要处理 mm 次更新。

结论:T<40mT<40m

其实和动态开点线段树是差不多一样的。