线段树学习笔记
经过这两天重新学习当时学过的线段树树,发现了很多当时没有注意到的问题。
首先是代码的熟练度,把acwing上的题都过了挑战模式之后终于有了一点点感觉,但是还远远不够
还需要大量的做题
今天(9.16)
需要完成acwing线段树所有的题目
luogu P6327
去写写luogu数据结构中的内容。
蓝书的清理班次。
y总tql,有些东西b
遇到的bug
1. modify进去之后sg,报错是P变成了无穷大,一直递归,可能是modify没有注意边界条件
2. query查询出来的值不对,可能是pushup和pushdown用了=,应该是+=
3. modify里边是if,if 不是if,else
4. 多个lazy标记怎么处理优先级的问题
5. 发现了一个重大的bug, 如果线段树结构体有很多标记的话,build的时候要对所有标记进行初始化,即使struct是定义在全局的,否则没有被初始化的标记会是随机值,尤其是dev不支持一起初始化,需要在struct中写两个初始化列表构造函数的时候。
学习目标
- 熟练线段树的四种操作
- 熟练扫描线
- 熟练线段树的动态开点
- 熟练线段树的合并
- 熟练线段树的可持久化
- 熟练权值线段树
- 熟练势能/jls线段树
- 熟练线段树的分裂
扩展内容:线段树优化DP,二维线段树,动态DP
扫描线学习笔记
扫描线本身的性质:
- 永远只考虑线段树根节点的信息。
- 不同于一般的query,扫面线的query不需要pushdown,因为只查询根节点的信息,queryO(1)
- 线段树维护的y轴中,维护的不是点,而是区间长度
- 扫描线,线段树中l,r表示的是一段区间,不是点,YL表示YL~YL+1
- 线段树里维护的区间不是点,将全体的y排序去重之后有,y1’,y2’,y3’,…,yk-1’,yk’
线段树中有k-1个节点,代表 y 1 ′ ∼ y 2 ′ , y 2 ′ ∼ y 3 ′ , y 3 ′ ∼ y 4 ′ , . . . y k − 2 ′ ∼ y k − 1 ′ , y k − 1 ′ ∼ y k ′ y1' \sim y2',y2' \sim y3',y3' \sim y4',...yk-2' \sim yk-1',yk-1' \sim yk' y1′∼y2′,y2′∼y3′,y3′∼y4′,...yk−2′∼yk−1′,yk−1′∼yk′
如果要在seg[i].y1(假设他是映射序列的yn’)到seg[i].y2(假设他是映射序列的ym’)这个区间上加上一个P,
就是在 y n ′ ∼ y n + 1 ′ , y n + 1 ′ ∼ y n + 2 ′ , . . . y m − 1 ′ ∼ y m ′ yn' \sim yn+1',yn+1' \sim yn+2',...ym-1' \sim ym' yn′∼yn+1′,yn+1′∼yn+2′,...ym−1′∼ym′上边都加上p,
- 线段树中每个“点”的含义是[x, x + 1]这段区间。所以线段树中u这个节点表示的是[tr[u].l, tr[u].l + 1], [tr[u].l + 1, tr[u].l + 2], …, [tr[u].r, tr[u].r + 1]这些小区间。
线段树学习路线
先把acwing上的线段树(不包括主席树)挑战模式过完
然后luogu上通过前三个模板,使用扫描线通过窗口的星星,过数学计算,小白逛公园
然后学习动态开点线段树,线段树的分裂和合并,树上差分,然后有多个选择
可以学习主席树,或者是树链剖分,。
还有李超线段树求函数定点极值,还有zwk线段树(非递归线段树)
然后整理一个线段树模板。
可持久化的话,学习可持久化线段树,可持久化数组,可持久化并查集,可持久化tire。
线段树合并和分裂
合并操作
总是忘记怎么写初始化列表,我脑子真笨
struct Node
{
int l,r;
ll sum,_add,_mul=1;
#define ls p<<1
#define rs p<<1|1
Node(){}
Node(int l,int r):l(l),r(r){}
}t[N*4];