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]处去答案。因为把当前节点的线段树合并之后,再操作其祖先,可能会涉及当前节点线段树上值的变化。

  • 相关阅读:
    让mysql查询强制走索引
    【转】起始时间和终止时间,循环输出每天
    【转】31个实用的find命令
    Hive数据倾斜解决办法总结
    网站架构之可扩展性
    网站架构之高可用性
    网站架构之可伸缩性
    kafka中的消费组
    MySQL知识点小结
    [数据挖掘]用户画像
  • 原文地址:https://www.cnblogs.com/fruitea/p/12018662.html
Copyright © 2011-2022 走看看