zoukankan      html  css  js  c++  java
  • 线段树入门之惊鸿一瞥

    --------------------------走吧,目标伟大航路!

    线段树的点点滴滴:

    线段树之所以称为“树”,是因为其具有树的结构特性。线段树由于本身是专门用来处理区间问题的(包括RMQRMQ、RSQRSQ问题等。)

    先从一些直观性的角度来看:

    上图是用二分法丫!问题来喽,

    对于给定区间[2,12]要如何分解成上述区间呢,何以分解之?

    分解方法一:自下而上合并——利于理解

    先考虑树的最下层,将所有在区间[2,12]内的点选中,然后,若相邻的点的直接父节点是同一个,

    那么就用这个父节点代替这两个节点(父节点在上一层)。这样操作之后,本层最多剩下两个节点。

    若最左侧被选中的节点是它父节点的右子树,那么这个节点会被剩下。若最右侧被选中的节点是它的父节点的左子树,那么这个节点会被剩下。

    中间的所有节点都被父节点取代。对最下层处理完之后,考虑它的上一层,继续进行同样的处理。

    继续沿用上面的那个引子图丫:

    这是n=13的线段树,区间[2,12],按照上面的叙述进行操作的过程图:

     

     

    由图可以看出:在n=13的线段树中,[2,12]=[2] + [3,4] + [5,7] + [8,10] + [11,12] 。

    分解方法二:自上而下分解——利于计算

     首先对于区间[1,13],计算(1+13)/2 = 7,于是将区间[2,12]“切割”成了[2,7]和[8,12]。

    其中[2,7]处于节点[1,7]的位置,[2,7] < [1,7] 所以继续分解,计算(1+7)/2 = 4, 于是将[2,7] 切割成[2,4]和[5,7]。

     [5,7]处于节点[5,7]的位置,所以不用继续分解,[2,4]处于区间[1,4]的位置,所以继续分解成[2]和[3,4]。

    最后【2】 < 【1,2】,所以计算(1+2)/2=1 ,将【2】用1切割,左侧为空,右侧为【2】

    所以【2,12】=【2】+【3,4】+【5,7】+【8,10】+【11,12】。

    当然程序是递归计算的,不是一层一层计算的,上图只表示计算方法,不代表计算顺序。-------------------------->递归工作栈的原理该怎么理解丫!

    对于每一个子节点而言,都表示整个序列中的一段子区间;对于每个叶子节点而言,都表示序列中的单个元素信息;子节点不断向自己的父亲节点传递信息(information),

    而父节点存储的信息则是他的每一个子节点信息的整合。

    皎月半酒花:

    有没有觉得很熟悉?对,线段树就是分块思想的树化或者说是对于信息处理的二进制化——用于达到O(logn)级别的处理速度,log2为底。

    (其实以几为底都只不过是个常数,可忽略)。而分块的思想,则是可以用一句话总结为:通过将整个序列分为有穷个小块,对于要查询的一段区间,

    总是可以整合成k个所分块与m个单个元素的信息的并(0<=k,m<=sqrt(n))。但普通的分块不能高效率地解决很多问题,所以作为log级别的数据结构,线段树应运而生。

     -----------------------------------------------------------------------------------------------------------------感谢诗鸿提供的博客图片。

  • 相关阅读:
    linux下yum无法使用
    判断某个网卡是否是dhcp获取的ip
    个人作业---词频统计
    第四周读书笔记
    设计关键词
    好文收藏
    Apritag角点代码检测
    处理txt文件,保存为yml和cal文件
    欧拉角欧拉矩阵
    Mysql笔记01-安装和SQL基础
  • 原文地址:https://www.cnblogs.com/dragondragon/p/11241530.html
Copyright © 2011-2022 走看看