线段树为什么要开4倍空间

线段树为什么要开4倍空间

Creation Time: 19 March 2014
Last Modified: 2014-03-23 01:01:26 scinart

最近在看《具体数学》,这篇当做是一个练习吧。

假设我们用一个数组来头轻脚重地存储一个线段树,根节点是1,孩子节点分别是2n, 2n+1, 那么,设线段长为L(即[1..L+1))

设树的高度为H,对H,有:

H(L)={1,L = 11+H(⌈L2⌉),L > 1

这是一个很简单的递归式,并用公式3.11逐次代换,就等到

H(L)=k+H(⌈L2k⌉),其中 k 是满足2k≥L的最小值

所以

H(L)=⌈lgL⌉+1.

所以显然所需空间为

2H−1=2⌈lgL⌉+1−1=2×2⌈lgL⌉−1≤2×2(L−1)−1,L≥2=4L−5,L≥2

转自http://scinart.github.io/acm/2014/03/19/acm-segment-tree-space-analysis/

时间: 2024-10-12 23:42:34

线段树为什么要开4倍空间的相关文章

线段树为什么开4倍空间?

突然想到,满二叉树不是才2n-1个节点么,为什么开4倍空间?? 因为线段树和二叉树是有一点区别的,线段树结点存的是区间,二叉树存的是点,所以线段树会出现许多结点空着的情况 见下图 所以,对于n个点,比n大的最小二次幂即为线段树最底层的结点数,所以所有结点数为 \[ 2^{\lfloor\log_2n\rfloor+1}*2-1 \] 即为4n 原文地址:https://www.cnblogs.com/Zeronera/p/11707603.html

刷题向》关于线段树的区间开根号 BZOJ3211

这是一道关于线段树的区间开根号的裸题,没什么好讲的. 值得注意的是,因为有区间开根号的性质,所以我们每一次更改操作只能把更改区间所覆盖的所有元素全部查找,当然你直接找效率明显爆炸... 能够注意到,指数级别的操作一次更改的数字都很大,而题目的数字最大是10的9次,所以可以注意到的是当一个区间更新6遍以后就失去更新的意义了,因为当你更改次数超过6次所有非负整数数字就全部会化为1.所以可以在每一个节点上加一个类似于LAZY标记的东西,记录开根号次数,以便节约跟新时间. 贴出题目&代码 Descrip

Hihocoder #1077 : RMQ问题再临-线段树(线段树:结构体建树+更新叶子往上+查询+巧妙使用father[]+线段树数组要开大4倍 *【模板】)

#1077 : RMQ问题再临-线段树 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 上回说到:小Hi给小Ho出了这样一道问题:假设整个货架上从左到右摆放了N种商品,并且依次标号为1到N,每次小Hi都给出一段区间[L, R],小Ho要做的是选出标号在这个区间内的所有商品重量最轻的一种,并且告诉小Hi这个商品的重量.但是在这个过程中,可能会因为其他人的各种行为,对 某些位置上的商品的重量产生改变(如更换了其他种类的商品). 小Ho提出了两种非常简单的方法,但是都不能

bzoj2212 Tree Rotations 线段树合并+动态开点

题目传送门 思路: 区间合并线段树的题,第一次写,对于一颗子树,无论这个子树怎么交换,都不会对其他子树的逆序对造成影响,所以就直接算逆序对就好. 注意叶子节点是1到n的全排列,所以每个权值都只会出现1次,合并很好写. 注意动态开点,最多n个叶子节点,然后每次查询用到log个子树节点,(这句话似乎有语病)所以要开nlogn的空间. #include<bits/stdc++.h> #define clr(a,b) memset(a,b,sizeof(a)) #define fpn() freope

poj 3667(线段树 区间合并) 开房吧

http://poj.org/problem?id=3667 宾馆有n个房间编号1到n都为空房,然后m个询问,当输入第一个为1的时候,代表要住进x个连续的房间,输入房间号最小的数,如果没有 输出0.当第一个数为2的时候,将从x号到y号的房间又变为空房,没有输出 与区间有关想想用线段树可不可以解决,就像是涂颜色一样把住与未住的房间号做个标记就行,问题是这里给的是区间的长度,并不是 具体的区间,处理起来比较麻烦 还要去找合适的区间,所以引入了len1表示某区间可用的最大长度,len2表示从区间左端开

kb-07线段树-08--区间开根

1 /* 2 hdu-4027 3 题目:区间开根求和查询: 4 因为是开根,所以要更新的话就要更新到叶子节点.如果区间里全是1或是0的话就步用继续更新了,查询的时候正常查询: 5 */ 6 #include<iostream> 7 #include<cstring> 8 #include<cstdio> 9 #include<cmath> 10 #define ll long long 11 using namespace std; 12 struct N

H - Can you answer these queries? HDU 4027 (线段树+延迟标记+开根号的速度)

H - Can you answer these queries? Time Limit:2000MS Memory Limit:65768KB 64bit IO Format:%I64d & %I64u Submit Status Practice HDU 4027 Description A lot of battleships of evil are arranged in a line before the battle. Our commander decides to use our

【BZOJ】3339: Rmq Problem &amp; 3585: mex(线段树+特殊的技巧)

http://www.lydsy.com/JudgeOnline/problem.php?id=3585 好神的题. 但是!!!!!!!!!!!!!!我线段树现在要开8倍空间才能过!!!!!!!!!!这什么梗...................... 我思考了很久空间的问题,因为我在pushdown的时候可能会越界,或许是pushup? 不管了.然后看了zyf的写法.看来以后得注意下...pushdown弄成先放了... 本题的做法: 好神orz 首先像莫队一样离线区间,左端点在前. 考虑如何

线段树相关知识点

线段树实现功能: 区间查找和更新 时间复杂度: 更新:O(logn)查找:O(logn) 线段树内存需要开四倍大小,切记!!! 为什么需要开到四倍? https://www.cnblogs.com/FengZeng666/p/11446827.html 理论上是2n-1的空间,但是你递归建立的时候当前节点为r,那么左右孩子分别是2*r,2*r+1,此时编译器并不知道递归已结束,因为你的结束条件是在递归之前的,所以编译器会认为下标访问出错,也就是空间开小了,应该再开大2倍.有时候可能你发现开2,3