线段树合并
一开始还以为线段树合并是什么高级操作。
学完后发现其实蛮简单的。
线段树合并,就是把两棵线段树的信息整合到一棵线段树上,只要动态开点递归处理就好了,如图:
上面这张图展示的就是把左边两棵线段树合并成右边那棵蓝色线段树的过程,还是很好理解的。
下面就是没有那么伪的线段树合并伪代码:
//[l,r]为当前所处理的区间
//x为第一棵线段树当前节点的编号
//y为第二棵线段树当前节点的编号
function node merge_trees(int l,int r,int x,int y)
{
if(x==null or y==null) //如果任意一棵线段树的当前节点为空
{
if(x==null) return y; //就直接返回非空节点
else return x;
}
if(l==r) //如果处理到了区间中只剩一个数了
{
int t = make_new_node(); //新建节点
t->val = x->val + y->val; //合并信息
t->lson = t->rson = null; //初始左右儿子
return t; //返回当前节点
}
int mid = (l + r) / 2 , t = make_new_node(); //求中点、新建节点
t->lson = merge_trees(l,mid,x->lson,y->lson); //递归处理左儿子
t->rson = merge_trees(mid + 1,r,x->rson,y->rson); //递归处理右儿子
t->val = t->lson->val + t->rson->val; //信息上传
return t; //记得要返回当前节点
}
不难看出,线段树合并的复杂度就是两棵线段树重合的节点的个数。
理解一下就好了。
例题:bzoj P2212 [Poi2011]Tree Rotations。
题解在这里。
参考文章在这里。