线段树合并
一、基本概念
線段樹合并:將已有的兩棵線段樹合并為一棵,相同位置的信息整合到一起,通常是權值線段樹比較裸的,就是將一棵線段樹的每一個位置取出來插入另一棵中,但比較高效的線段樹合并可以參照可并堆的合并方式
二、算法
假設兩棵線段樹樹:
?
合并
??
線段樹合并的原理:
對于兩顆樹的節點u和v
①如果u為空,返回v
②如果v為空,返回u
③否則,新建節點t,整合u和v的信息,然后遞歸合并u和v的左右子樹
過程示例
?
三、代碼
關鍵代碼:
int merge(int u,int v){if (!u) return v;if (!v) return u;int t = ++cnt;sum[t] = sum[u] + sum[v];ls[t] = merge(ls[u],ls[v]);rs[t] = merge(rs[u],rs[v]);return t; }合并的復雜度取決于兩棵線段樹重合的部分的大小
每有一個位置權值同樣存在,就要O(logn)的復雜度
不過,由于權值線段樹中被更新的位置通常很均勻分布,所以合并的兩棵線段樹通常具有很小的相似性?
四、例題
https://www.luogu.org/problemnew/show/P3224
https://www.lydsy.com/JudgeOnline/problem.php?id=2733(題解:https://blog.csdn.net/weixin_43272781/article/details/95371733)
五、參考文章
https://www.cnblogs.com/Mychael/p/8665589.html
https://www.cnblogs.com/owencodeisking/p/9965525.html
https://www.cnblogs.com/wozaixuexi/p/9365198.html
https://blog.csdn.net/keydou/article/details/83691189
總結
- 上一篇: BZOJ 2733 | 洛谷 P3224
- 下一篇: C++ scanf()函数安全性问题