一、概述
线段树是一种在线算法,它在各个节点保存一条线段(数组中的一段子数组),主要用于高效解决连续区间的动态查询问题,由于二叉结构的特性,它基本能保持每个操作的复杂度为O(logn)。
二、原理分析及代码实现
我们从一个经典的例子来了解线段树,问题描如下:从数组arr[0...n-1]中查找某个数组某个区间内的最小值,数组中的元素的值可以随时更新。这使我们非常困扰,因为当数组非常大的时候,就很容易TLE,所以我们亟待一种相对高效的算法,线段树应运而生。
1,建树。
假如我们要对8个数据进行管理,我们就要建立一个线段树。建立的线段树是一个完全二叉树,我们需要借助一个二叉树的性质:
父亲的区间是[a,b],(c=(a+b)/2)左儿子的区间是[a,c],右儿子的区间是[c+1,b],所以线段树需要的空间为数组大小的四倍。
函数声明(我们需要根节点,左右两个儿子),如果到底了,本节点就等于要记载的数组的节点并返回,这也是递归的边界条件,接下来利用性质构筑左右子树mid=(left+right)/2;build(2*root,left,mid);build(2*root+1,mid+1,right),递归完成后,父节点更新。
2、单点更新
现在树已经建立完毕,但这还是刚刚开始的存图环节,假如说现在我们要使一个节点更新,比如让第三个数所对应的arr【3】+5,会产生“牵一发而动全身”的效应,所以们们需要对它上面的节点再次更新。
假如arr【1-8】为 1,8,7,3,9,2,4,6 如图所示:
我们要对数组3加上一个5,要达到以下结果。
我们需要对每一个节点更新,使用的数据有本次的根节点,要控制的总范围区间(左,右),要修改的点和要修改的数据。持续更新它的父节点直到顶端即可。
3,区间更新
区间更新是个大问题,很多同学会想到用一个for循环,每个点走一遍。虽说思维难度不大,而且在点与点范围跳跃速度也不慢,但当要修改的数据到达一定规模时,这样重复的操作显得累赘而消耗巨量时间,非常容易TLE。所以我们需要找到之间重复的规律,简化程序,以减少不必要的时间浪费。
于是我们想到了一个方法