线段树总结
线段树
你说的对,但线段树是一种用 \(O(n \cdot log \ n)\) 的大常数复杂度+略微的卡常下技巧=AC 的妙妙数据结构。
线段树是基于分治与二叉树的在线工具,可以维护区间信息,但比树状数组能够维护的东西更多。
线段树虽然能够维护的东西更多,但也有一些特别显著的缺点:
- 代码量过长。
- 查错不好查。
- 大常数超时。
线段树其所对应的时空复杂度对应 $n \in [10^5,5\times 10^5] $。
在线段树中,节点的左儿子为 \(2x\) ,右儿子为 \(2x+1\)。
一些易错点
线段树数组要乘 \(4\)
原因:
线段树是一种二叉树结构,其结构若为完全二叉树,则其所需空间为:
\( 1+2+4+......+n/4+n/2+n=2n-1 \)
但是实际应用中最后一层远远铺不满,所以最后一层的编号用不全,最坏情况是只用了最后一层的最后一个,为上一层编号再 \(\times 2\),所以要乘上 \(2 \times 2=4\) 倍。
线段树在修改与查询时,查询区间不变
比较常犯的一个错误,因为写 build(int p,int l,int r) 时,l 代表当前区间左端点,r 代表区间右端点,所以递归时要 build(p*2,l,mid) 与 build(p*2+1,mid+1,r)。
但是在修改与查询中 ask(int p,int l,int r) 中,l、r 代表查询区间的左右端点,算是定值,不能更改。
在询问与修改中,\(mid=(l+r)>>1\)
很明显的一个错,但总是查不出来。
应该为 \(mid=(seg[p].l+seg[p].r)>>1\)
在修改中,为往上更改节点所存的值。
不必多言,注意了也经常错。
在建树(build 函数)时,没有 return
当你犯过一次并为此投入 \(1.5 h\) 的代价后,你会记住的.......
$ {\tiny 真实事件改编而来} $
To Be Continued
以下提供线段树查错思路
以上四种错误(除第 \(4\) 种)都会导致 \(RE(Segmentation\ \ fault\ \ with \ \ invalid \ \ memory \ \ reference.)\),如下。

如果不是 \(RE\),建议查其他错误。
建议:
- 先查线段树数组是否 \(\times 4\)。
- 查询问与更改时,函数参数是否发生了不对的变化,见上第 \(2\) 点。
- 同时检查第 \(3\) 点。
- 最后再看
build函数。
例题
【线段树模板题】序列操作1
板子。
F - Second Largest Query
进行分类讨论,我们也可以选择排序后选前两大,思维上难度较小。
A Simple Problem with Integers
懒惰标签板子。
维护序列-区间乘与区间加
维护两个懒惰标签,形如:
\(
k\times mul+add
\)
区间加可直接加,区间乘需要将 \(add\) 同时乘。
花神游历各国
结论题,注意到 \(a \le 10^9\) 只够开平方 \(5\) 次,前 \(5\) 次可暴力做,后面可以打个标签。
注意:
特殊判断 \(a_i\) 是否为 \(0\)。
无聊的序列
差分之,操作一等效为区间加;操作二等效为区间求和。
E - Simple String Queries
线段树中维护 bitset。
G - Smaller Sum
线段树中维护 vector。

浙公网安备 33010602011771号