//定义线段树
struct node
{
int sum,lazy;
}tree[manx<<2];
(下面没有讨论公式的证明)
先标几个重点:
- 如果区间长度为N,那么构造的线段树的叶子结点个数就是N
- 深度为k-1的满二叉树有2k-1 -1个结点,且第k层的节点数是: 2k-1
- 假设线段树最后一层的叶子结点为m,倒数第二层叶子结点为n,(n+m=N)
由1、2可知,线段树结点个数为2(m/2+n)-1+m=2N+1(但是我们开了4N) - 如果一个子树根结点的编号为root, 那么他的左孩子编号为 , 右孩子编号为 (也是因为这个性质,构造线段树需要多开一些空间)
- 定义:mid=(l+r)/2;
tree[root].sum——表示 [l, r] 的区间和
tree[chl].sum——表示 [l, mid] 的区间和
tree[chr].sum——表示 [mid+1, r] 的区间和
(从这里也可以看出,两个区间段要么长度相等,要么右边多一个)
然后讨论需要开的空间大小
- 最好的情况,就是满二叉树:
- 如果在再加一个结点,(肯定挂在右边)
上面两种情况都不用开多余的空间,2N-1都可以解决
- 再加一个,(就挂左边了)
由前面第3点可知,在区间为[1,10]的线段树中,如果我们要访问[6,7]这两个点,就需要在最后一层多开中间的那4个空间,虽然不会用他们储存信息,(如果直接从最左边挨着挂过去,当然2N-1就够了)
从上面也可以看出,如果线段树叶子结点为N个,那么n
N
那么根据满二叉树的性质,除“最后一层”,的总结点数
2N-1
如果“最后一层”开满的话,“最后一层”节点数
2N
————一共4N-1,所以开4N也一定不会超内存