线段树合并初探

线段树合并

线段树合并就是把两棵权值线段树给合并起来,复杂度\(O(nlogn)\)
值得注意的是:是两棵线段树对应位置进行合并操作!
有两种写法:

inline int merge(int x,int y,int l,int r){
    	if(!x||!y)return x+y;
    	if(l==r){tr[x]+=tr[y];return x;}
    	int mid=(l+r)>>1;
    	ls[x]=merge(ls[x],ls[y],l,mid);rs[x]=merge(rs[x],rs[y],mid+1,r);
    	pushup(x);return x;
}

这种是把y合并到x上。但是这种合并过程中有可能会破坏x,y的结构。所以适合把询问都离线下来,一合并完就回答询问。

另一种写法是类似主席树,新开节点。这种不需要把询问离线,但是空间花费大。

inline int merge(int x,int y,int l,int r) {
    	if(!x||!y)return x+y;
    	int rt=++cnt;
    	if(l==r) {tr[rt]=tr[x]+tr[y];return rt;}
    	int mid=(l+r)>>1;
    	ls[rt]=merge(ls[x],ls[y],l,mid);rs[rt]=merge(rs[x],rs[y],mid+1,r);
    	pushup(rt);return rt;
}

例题

[POI2011]ROT-Tree Rotations

Link
前序遍历 根\(\rightarrow\)\(\rightarrow\)右。所以逆序对无非左子树内部、右子树内部、跨越根节点三种。前两种递归计算,最后一种对两侧开权值线段树,线段树合并计算。

[Vani有约会]雨天的尾巴

Link
dfs时做完这个节点就要在rt[i]处取他的答案,不能在dfs整棵树之后再在rt[i]处去答案。因为把当前节点的线段树合并之后,再操作其祖先,可能会涉及当前节点线段树上值的变化。

posted @ 2019-12-10 19:30  Fruitea  阅读(265)  评论(0编辑  收藏  举报