线段树模板与练习
文章和代码已经归档至【Github 仓库:algorithms-notes】或者公众号【AIShareLab】回复 算法笔记 也可获取。
应用:求区间最大值,求染色面积,长度,最大连续和等等。
思想
操作一:单点修改 ()
单点修改的基础思想就是仅修改信息需要变化的节点,类似一个递归 + 回溯的过程。
操作二:区间查询 ()
查询也是一个递归的过程,如果查询的区间已经把当前区间完全包含了,则可以返回该区间了。
此外,进行区间修改往往会使用懒标记。
核心函数
pushup:用子节点信息更新当前节点信息
build:在一段区间上初始化线段树
modify:修改
query:查询
(此外,懒标记会有 pushdown)
存储方式
线段数组的存储方式与堆(heap)的存储方式类似,采用了一维数组:
对于节点 x:
父节点为 ,记为
x >> 1
左儿子为 2x,记为
x << 1
右儿子为 2x + 1,记为
x << 1 | 1
关于数组存储的空间问题:最理想情况是 ,一般情况下最后一层节点不是满的,但最坏情况也不会超过前面整个二叉树的节点总数,也就是不会超过 2N−1,所以一共最多不会超过 4N。这里 N 如果不是 2 的整次幂就是倒数第二层,否则就是最后一层。
模板:动态求连续区间和
给定 n 个数组成的一个数列,规定有两种操作,一是修改某个元素,二是求子数列 [a,b] 的连续和。
输入格式
第一行包含两个整数 n 和 m,分别表示数的个数和操作次数。
第二行包含 n 个整数,表示完整数列。
接下来 m 行,每行包含三个整数 k,a,b (k=0,表示求子数列[a,b]的和;k=1,表示第 a 个数加 b)。
数列从 1 开始计数。
输出格式
输出若干行数字,表示 k=0 时,对应的子数列 [a,b] 的连续和。
数据范围
,
,
,
数据保证在任何时候,数列中所有元素之和均在 int 范围内。
输入样例:
输出样例:
code
练习:数列区间最大值
输入一串数字,给你 M 个询问,每次询问就给你两个数字 X,Y,要求你说出 X 到 Y 这段区间内的最大数。
输入格式
第一行两个整数 N,M 表示数字的个数和要询问的次数;
接下来一行为 N 个数;
接下来 M 行,每行都有两个整数 X,Y。
输出格式
输出共 M 行,每行输出一个数。
数据范围
,
,
,
数列中的数字均不超过
输入样例:
输出样例:
code
版权声明: 本文为 InfoQ 作者【timerring】的原创文章。
原文链接:【http://xie.infoq.cn/article/d152f6f8524bf67e0e0d68e22】。未经作者许可,禁止转载。
评论