zoukankan      html  css  js  c++  java
  • 线段树合并初探

    线段树合并

    线段树合并就是把两棵权值线段树给合并起来,复杂度(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
    前序遍历 根( ightarrow)( ightarrow)右。所以逆序对无非左子树内部、右子树内部、跨越根节点三种。前两种递归计算,最后一种对两侧开权值线段树,线段树合并计算。

    [Vani有约会]雨天的尾巴

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

  • 相关阅读:
    (元)黄公望---富春山居图(中国十大传世名画之八) 高清图下载
    Bloom Filter 原理与应用
    开始我的 JNI 入门吧
    javaScript的使用
    hash定义
    POJ3169 Layout(差分约束系统)
    青蛙的约会
    POJ 3414 Pots ( BFS , 打印路径 )
    你真的理解Java的this和super吗?
    十款优秀的在线JavaScript工具介绍
  • 原文地址:https://www.cnblogs.com/fruitea/p/12018662.html
Copyright © 2011-2022 走看看