线段树 - 更加细致地维护区间可加信息
I.综述&解释
线段树,是一种树形结构其上每一个点都是一个区间,维护了该区间上的某些信息,故称“线段树”(SegmentTree)。
这种数据结构能够维护区间上的信息,支持单点/区间修改/查询,是一种更加通用的结构,变化多端,应用广泛,只要满足区间可加性的信息就能够使用,经过某些转化后具有区间可加性的也可以使用(e.g. 区间最大子段和)。
可以明显看到的是,虽然单次操作的理论复杂度一致,线段树还是劣于树状数组,不过其思维与代码清晰度其实略胜一筹,时间也可以接受,扩展性好。
II.起源
写到这我发现“起源”这个小标不太合适,因为都写的不想起源了。
那么线段树,就是用于维护区间信息的,可以发现的是,线段树的线段长度仍然是2的整数次幂。是的,这种运用分治和分块思想的数据结构依旧使用以上定理。
其实在上一篇树状数组里提到的那个想求不可差分信息的改版也和这有相似之处,只不过因为数组数组的存储特征,无法保证任意区间都有已经处理好的信息可用,所以最后只能选择合并单点。
而线段树的划分无关下标的二进制位,而是关于区间长度,所以是一种更加通用的结构,它保证无论在什么地方的区间都能通过不超过次递归找到合适的分配。
但是,这也许就决定了线段树的常数必然比树状数组大得多,如果查询区间恰好是在特别的位置,它就需要分别递归多次,访问的节点会变多。
不过,线段树耗费了更多空间存储区间信息,这使得它可以维护不可差分信息,只要满足可加性就行了。
它的区间划分比那个尝试食用树状数组求区间max的更加高效,不会导致太多的时候只能加单点,所以效率更加高。
III.基(本)操(作)
- 向上更新(update)
用两个子区间的信息更新父区间。
- 向下传递(spread)
向两个子区间传递“延迟修改标记”(lazy tag)并进行对应修改
- 初始化(build)
从最大区间开始向左右两半递归,直至元区间[x,x]并填充信息。随后执行update操作
- 单点修改(modify)
递归到元区间随后修改,然后在回溯时执行update操作
- 区间修改(modify)
向下递归直到找到被修改区间包含在内的线段(此过程中执行spread),添加lazy tag并回溯,此时执行update操作。
- 区间查询(query)
向下递归直到找到被修改区间包含在内的线段(此过程中执行spread),累计答案并回溯。
本文来自博客园,作者:haozexu,转载请注明原文链接:https://www.cnblogs.com/haozexu/p/18281776

浙公网安备 33010602011771号