[线段树系列 #2] 动态开点线段树
[线段树系列 #2] 动态开点线段树
简单介绍
动态开点线段树最出名也是最广为人知的一点就是:省空间
你可以理解为 当有一个新的节点 \((x,v)\) 插入时 我们只建了从 1 到 \(x\) 的一条链
所以 原普通线段树 \(1-n\) 的大约 \(4n\) 个点,我们只需建 \(m\log n\) 个点(其中 \(m\) 为插入次数)
思路概述
在原 SegmentTree 结构体中新增两个变量 \(l,r\),分别为左右儿子编号
一开始,只有一个根节点,每次操作插入新节点,并通过递归新建点与记录儿子节点编号
具体实现
// 插入新节点
void update(int &p, int l, int r, int x, int v){
if(!p) p = ++cnt;
if(l == r){
t[p].v += v;
return;
}
int mid = (l+r) >> 1;
if(x <= mid) update(t[p].l, l, mid, x, v);
else update(t[p].r, mid+1, r, x, v);
pushup(p);
}
剩余操作与普通线段树并无太大区别,只是把左右儿子的 \(p\times 2\) 和 \(p\times 2+1\) 改为了 t[p].l 和 t[p].r
应用
动态开点线段树常与离散化结合,建立权值线段树,维护信息

浙公网安备 33010602011771号