[线段树系列 #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

应用

动态开点线段树常与离散化结合,建立权值线段树,维护信息

还辅助支持如线段树合并线段树分裂等更多操作

posted @ 2025-07-14 16:13  Hirasawayuiii  阅读(15)  评论(0)    收藏  举报