[线段树系列 #3] 线段树合并
[线段树系列 #3] 线段树合并
简单介绍
线段树合并,通常是对于维护同样的一个区间的动态开点线段树来说的(普通线段树每个节点都是对应的,直接相加即可)。
它可以将多个线段树合并为一个线段树,以来记录答案
思路概述
假设两颗线段树为 A 和 B,我们从 1 号节点开始递归合并。
递归到某个节点时,如果 A 树或者 B 树上的对应节点为空,直接返回另一个树上对应节点,这里运用了动态开点线段树的特性。
如果递归到叶子节点,我们合并两棵树上的对应节点。
最后,根据子节点更新当前节点并且返回。
(摘自 OI Wiki)
时间复杂度上,对于两棵满线段树,单次合并显然为 \(O(n\log n)\) 的,但线段树合并通常作用于权值动态开点线段树,合并结束后增加的点的数量大约为 \(n\log n\) 级别的,所以总复杂度也大致在 \(O(n\log n)\) 左右。
具体实现
void merge(int &x, int y, int l, int r){
if(!x){
x = y;
return;
}
if(!y) return;
if(l == r){
t[x].c += t[y].c;
return;
}
int mid = (l+r) >> 1;
merge(t[x].l, t[y].l, l, mid);
merge(t[x].r, t[y].r, mid+1, r);
}