线段树学习笔记与总结
线段树
引入
我们经常会遇到需要维护一个序列的问题,例如给定一个整数序列,每次操作会修改序列某个位置上的数,或是海间你序列巾某个区问内所有数的和,用“暴力"算法,单点修改的复杂度为 \(O(1)\),询问区间和的单次复杂度为 \(O(N)\)。用前缀和算法,询问区间和的单次复杂度为 \(O(1)\),但单点修改的复杂度为 \(O(N)\)。这类问题的 \(m\) (询问次数)和 \(n\)(区间长度)往往是 \(10^5\) 数量级的,这两种算法都会失效。线段树就是用来处理类似这样,在序列上单点修改、区间询问(或是区间修改,单点询问,甚至是区间修改、区间询问)的间题的一种数据结构,相比于朴素算法 \(O(n^2)\) 的时间复杂度,线段快能在 \(O(nlogn)\) 的时间复杂度下解决问题
资源链接
OI Wiki - 线段树
AcWing 1 - 单点修改、区间询问
AcWing 2 - 区间修改、区间询问
模板
用结构体 struct
储存线段树更为方便
struct Node
{
int l, r; // 区间
type xxx; // 需要的值
}
一般有五个操作函数
void pushup() // 由子节点更新父节点(更新所储存的值sum/max/min)
void pushdown() // 由父节点更新子节点(懒惰/延迟标记)
void build() // 构建
void modify() // 更改
type query() // 查询