理解
顾名思义,就是把两棵线段树的信息合并起来。
暴力合并很好想,把两棵树一起遍历一遍就是了,复杂度
但是很多情况下我们需要多次合并两棵并不饱满的线段树(此处“不饱满”意思是有些区间根本没有用过),空间和时间都过不去,
所以就用到一些优化。
思路
怎么优化空间呢?很简单,动态开点。
(这里不开链接了,直接安利一下动态开点,懂的跳过:
其实就是把每个节点的左右儿子记录(不再用id*2,id*2+1直接访问),初始为零,当需要往下插入时才赋值为两个新的点(简称开点),查询就不用开点了,特判一下就行
完了)
使用了动态开点后,你再用暴力遍历的方式合并:
inline int mergg(int x,int y,int l,int r){
if(!x||!y)return x|y; //两节点其中一个为零,另一个补上去
int mid=(l+r)>>1;
t[x].ls=mergg(t[x].ls,t[y].ls,l,mid),t[y].ls=0; //合并左子树
t[x].rs=mergg(t[x].rs,t[y].rs,mid+1,r),t[y].rs=0; //合并右子树
.../*此处合并两点信息*/
return x;
}
虽然看上去还是O(n),但是(大多数问题中)当每次合并的树的大小总和有限制的时候,总复杂度是,比非动态的快得多。
例题:ZZH的旅行