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

应用

P4556 [Vani有约会] 雨天的尾巴 /【模板】线段树合并

P1600 [NOIP 2016 提高组] 天天爱跑步

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