线段树 解题技巧
编程技巧
普通线段树
难点主要集中在标签下放与合并
在编程更新函数时,要考虑对同一区间反复更新不同标签的合并优先级;
该优先级也同样会应用到标签下放操作上。
分治
可以左右对半分,可以偏左子树,可以偏右子树,完全服务于题目。
二分
二分依赖单调性,答案要么在左孩子,要么在右孩子,故而考虑左右孩子的优先级。
假设当前数组为升序,用其初始化线段树,求大于v
的最小值下标。
那么应该保存每个区间的最大值,如果左孩子的最大值大于v
,说明可能存在解,优先处理左孩子;
因为数组是升序,假设左右孩子都有解,显然左孩子的解才是正确答案。
动态开点
一般用在区间范围过大,无法使用普通线段树的情况下。
普通线段树的空间开销是4 * 数据范围
,动态开点线段树的空间开销是询问次数 * log数据范围
,小了很多。
动态开点的编程也与普通线段树有细微差距,区间范围通过函数的参数传递,如果左右孩子不存在需要即时创建。
合并
有合并、主席树两种思维。
合并思维并不会新开额外空间,是因为把所有子树的数据并到父树上;
但存在致命缺陷,父树合并子树结构后,子树很有可能会在父树合并期间被篡改原有数据,
所以不可以在合并后进行子区间的访问。
主席树思维则没有这个弊端,毕竟每次合并都会新开一个节点;当然代价就是空间占用过大,毕竟相当于直接新建一颗新树。
1 | // 合并思维 |
1 | // 主席树新建节点思维 |
练习题
- P3372 区间和
- P3870 区间取反
- P1438 差分、区间和
- P1253 多标签处理(多标签可以抵消),区间覆盖、区间新增、区间极值
- P3373 多标签处理(多标签可以抵消),区间乘法,区间加法
- P4513 分治(左右孩子互不影响)
- P1471 区间方差和
- P4692 分治(左右孩子互不影响)
- P1637 权值线段树/权值树状数组
- P1558 区间与运算,状态压缩
- P5522 区间交运算,状态压缩
- 689D 区间极值
- P4145 势能线段树
- P2572 分治(左右孩子互不影响),多标签处理,区间覆盖,区间取反;模板题
- P4198 分治(左孩子影响右孩子),模板题
- P5579 线段树二分,最大值里找最小
- 2828 线段树二分,答案要么在左孩子要么在右
- 4747 线段树二分,最大找最小
- 19D 线段树二分,set优化,满足条件下找最小,模板题
- P5459 动态开点线段树
- 915E 动态开点线段树,模板题
- 353 线段树合并,LCA,树上差分,合并写法,模板题
- P3899 线段树合并,主席树写法,模板题
- P3224 线段树合并,并查集
- P3605 线段树合并
- P3521 线段树合并,逆序对