线段树之入门篇

线段树(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相加即可。

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

时间: 2024-10-10 02:45:24

线段树之入门篇的相关文章

hdu 1754:I Hate It(线段树,入门题,RMQ问题)

I Hate It Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 33726    Accepted Submission(s): 13266 Problem Description 很多学校流行一种比较的习惯.老师们很喜欢询问,从某某到某某当中,分数最高的是多少.这让很多学生很反感.不管你喜不喜欢,现在需要你做的是,就是按照老师的要求

线段树--从入门到精通

线段树,强大的数据结构,用处也是比较广的. 首先,我们要明白线段树是个啥? 线段树,线段嘛,有左右端点,那么它当然可以代表一个区间,那么区间上的好多事情都可以用它来搞,比如:区间加,区间乘,区间求和. 首先让我们先看个线段树的模型. 如图,这就是一棵线段树的模型. 圈内的点表示这是第几个点,红色表示这个点表示的区间范围. 每个点和它的左右两个儿子的编号是有一定的关系的: 点N,它的左儿子编号为N$\times$2,右儿子编号为N$\times$2+1. 线段树支持单点修改,区间修改,单点查询,区

主席树(入门篇)

主席树 write by BigYellowDog 前置知识:线段树.离散化.前缀和.最好还有Splay 主席树是什么? 首先跟你说说这名字的由来.据说,是一位叫fotile主席的大大在写一道题时因为不会划分树就临时yy出一个算法,于是,这算法就这么诞生了.(这就是大佬吗Orz-) 主席树全称叫可持续化线段树,好复杂.其实就是可以重复利用信息的线段树,从而减小空间和时间的开销.举个例子,为了做到重复利用信息,它时这个样子的: 去孤独·粲泽博客找的的图片,ta讲的也特别好辣,推荐大家去看看 看到没

HDU 1166 敌兵布阵 (线段树 & 树状数组)

敌兵布阵 Time Limit:1000MS    Memory Limit:32768KB    64bit IO Format:%I64d & %I64u SubmitStatus 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1166 Description C国的死对头A国这段时间正在进行军事演习,所以C国间谍头子Derek和他手下Tidy又开始忙乎了.A国在海岸线沿直线布置了N个工兵营地,Derek和Tidy的任务就是要监视这些工兵营地的

HDU 1754 I Hate It (线段树 & 树状数组)

I Hate It Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 39959 Accepted Submission(s): 15863 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1754 Problem Description 很多学校流行一种比较的习惯.老师们很喜欢询问,从某某到某某当

线段树入门---给定多个线段求点的出现个数

线段树是一颗二叉树,他的每个节点都是一个区间,此题为线段树的入门题目,只是学习笔记.例题:给定N个线段,给定M个点,求点在多少个线段中出现过,此时如果用传统的方法来求,时间复杂度太高,但是,线段树的时间复杂度还可以接受. 步骤为: 1. 首先找一个区间,能覆盖给定的所有区间, 然后把此区间建立线段树,建立线段树的方式是二分法建立,即它的左孩子是他的左半个区间,右孩子是它的右边那个区间.一个图足以说明清楚 2. 将所有的区间映射到此树上, 从根节点开始遍历, 每遍历一个节点考虑四种情况: 1) 当

bzoj-1012 1012: [JSOI2008]最大数maxnumber(线段树)

题目链接: 1012: [JSOI2008]最大数maxnumber Time Limit: 3 Sec  Memory Limit: 162 MB Description 现在请求你维护一个数列,要求提供以下两种操作:1. 查询操作.语法:Q L 功能:查询当前数列中末尾L个数中的最大的数,并输出这个数的值.限制:L不超过当前数列的长度.2. 插入操作.语法:A n 功能:将n加上t,其中t是最近一次查询操作的答案(如果还未执行过查询操作,则t=0),并将所得结果对一个固定的常数D取模,将所得

白话数据结构之【线段树】

线段树的入门 线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点. 对于线段树中的每一个非叶子节点[a,b],它的左儿子表示的区间为[a,(a+b)/2],右儿子表示的区间为[(a+b)/2+1,b].因此线段树是平衡二叉树,最后的子节点数目为N,即整个线段区间的长度. 使用线段树可以快速的查找某一个节点在若干条线段中出现的次数,时间复杂度为O(logN).而未优化的空间复杂度为2N,因此有时需要离散化让空间压缩. ----来自百度百科 [

codeforces 339C Xenia and Bit Operations(线段树水题)

转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud Xenia and Bit Operations Xenia the beginner programmer has a sequence a, consisting of 2n non-negative integers: a1, a2, ..., a2n. Xenia is currently studying bit operations. To better unders