• 线段树入门


     // 转载自:http://www.cnblogs.com/superbin/archive/2010/08/02/1790467.html

    感觉讲的很详细。也很实用。果断转~感谢楼主~~~

    线段树入门

    线段树(interval tree) 是把区间逐次二分得到的一树状结构,它反映了包括归并排序在内的很多分治算法的问题求解方式。

    上图是一棵典型的线段树,它对区间[1,10]进行分割,直到单个点。这棵树的特点
    是:
    1. 每一层都是区间[a, b]的一个划分,记 L = b - a

    2. 一共有log2L层
    3. 给定一个点p,从根到叶子p上的所有区间都包含点p,且其他区间都不包含点p。
    4. 给定一个区间[l; r],可以把它分解为不超过2log2 L条不相交线段的并。
    其中第四点并不是很显然,图8.1显示了[2, 8]的分解方式,深灰色结点为分解后的
    区间,浅灰色结点是递归分解过程中经过的结点。为了叙述方便,下面称树中的结点
    所对应的区间为树中区间。

      从第3点和第4点可以得出结论:修改一个点只用修改log2 L个树中区间信息,而统计一个区间只需要累加2log2 L个树中区间的信息,且访问的总结点数是O(log L)的。两个操作都很容易实现。
      动态统计问题I 有一个包含n个元素的整数数组A,每次可以修改一个元素,也可以询问某一个区间[l; r]内所有元素的和。如何设计算法,使得修改和询问操作的时间复杂度尽量低?
      方法一 直接做, 则修改操作是O(1)的, 但询问需要进行累加, 时间复杂度为O(r ¡ l),最坏情况为O(n)。
      方法二 建立一棵线段树,每个树中区间记录该区间的元素和,则由刚才的结论,修改元素时只需要修改log2 L个树中区间的元素和,而统计时只需要累加2log2 L个树中区间的元素和,两个操作都是O(log n)的,比方法一好很多。
      动态统计问题II 有一个包含n个元素的整数数组A,每次可以同时给一个区间[l; r]内的数同时增加一个数d(d可以为负),也可以询问某一个数Ai的值。如何设计算法,使得修改和询问操作的时间复杂度尽量低?

      如何快速修改一个区间?修改一个树中区间[a; b]将影响到以[a; b]为根的整棵子树和它的所有祖先,所以如果沿用刚才的线段树定义,是不可能快速实现区间修改操作的。
      解决方法是借用数据结构中常用的懒操作"的思想,只记录有哪些操作需要执行,而不去真正执行这些操作。换句话说,在需要给树中区间[l; r]的元素同时增
    加 d时,我们只记录曾经有一条指令add(l, r, d)"就可以了。我们把记录的这个值称为树中区间的add值,则叶结点的元素值为它所有祖先的add值之和。根据前面的结论,每一条任意区间的修改指令可 以分解成2log2 L个树中区间的修改指令,且修改操作具有叠加性,因此修改操作的时间复杂度为O(log n)。查询操作只
    需要累加叶子的所有祖先,它也是O(log n)的。
      动态统计问题III 有一个包含n个元素的整数数组A,每次可以同时给一个区间[l; r]内的数同时增加一个数d(d可以为负),也可以询问一个区间[l; r]内所有元素的和。如何设计算法,使得修改和询问操作的时间复杂度尽量低?

      显然前两个问题都是此问题的特殊情况,因此这个问题比前两个问题难度更大。注意到上一个问题线段树只能提供叶结点的真正元素和,因为对于任何一 个树中区间[l; r]来说,影响它的指令所修改的区间不仅包括它的所有祖先,也包括它的所有后代。所以[l; r]内的所有元素和应该等于[l; r]的所有祖先的add值加上[l; r]所有后代的add值。

      但后代有很多,直接累加的时间开销过大。这里需要再一次利用线段的树的区间相加性质,记录一个附加值sum_of_add,表示以[l; r]为根的子树上所有树中区间的add值之和。
      修改操作把区间分解为树中区间,修改它们的add值,并且要顺便修改它们父亲的sum_off_add值。由于区间分解过程访问的总结点是O(log L)的,因此修改操作是O(log n)的。
      查询操作把区间分解为树中区间,并统计它们所有祖先的add值之和,再与这些树中区间本身的sum_off_add相加即可。

    文章出自《算法艺术与信息学竞赛》 ---- 作者:刘汝佳

  • 相关阅读:
    OpenCV图片类cv::Mat和QImage之间进行转换(好多相关文章)
    在 .pro里加入 QMAKE_CXXFLAGS += /MP 将并行编译(VC),加快编译速度(姚冬的办法),或者-j4参数(MinGW)
    GUI为什么不设计为多线程(用户事件和底层事件的流程是相反的,每层都加锁效率太低,共用一把锁那就是单线程)
    QML的渲染方式相较于之前的版本也有了重大的更新(CPU线程负责绘制,GPU线程负责渲染),还有好多经常评论 good
    分析Sizzle引擎
    当Azure里的虚拟机网卡被禁用
    SQL Server跨网段(跨机房)FTP复制
    公众平台Bee.WeiXin
    使用Jquery+EasyUI进行框架项目开发案例讲解之一---员工管理源码分享
    阿里巴巴笔试
  • 原文地址:https://www.cnblogs.com/icode-girl/p/4832474.html
Copyright © 2020-2023  润新知