线段树是一种很实用的数据结构,所以也要学习一下。
线段树是用来处理区间问题的,复杂度能到达 O(logn)。
就以洛谷的模板题 线段树 1 为例吧。
1.将某区间每一个数加上x
2.求出某区间每一个数的和
很显然,这道题是要写一个维护区间和的线段树。
就拿代码说吧。
建树
因为线段树是一棵二叉树,所以如果一个结点的编号为 i 那么其左右子结点编号分别为 2i 和 2i+1(用位运算可以如下表示)
因为要维护区间和,所以要这么写。
递归建树。
如果左右区间相同说明它是叶子节点,所以就记录输入数据的信息然后 return
就好啦。
区间修改
我们用 add
记录每个节点每次要更新的值,传递式记录,这样有利于减少复杂度。
注意:add
在建树时就已经初始化好了,其实在这里也可以初始化。
下面用 delta()
函数来进行区间更新操作,因为是对区间进行操作,所以最后要乘上区间长度(即区间元素个数)。
push_down()
来维护区间更新,每次更新两个子节点并向下传递。
下面的代码中,用 sb, se
表示要修改的区间,l, r
表示节点 o
所存的区间。(emm,参数有些长啊~~,但强迫症不想用 typedef
~~)
区间查询
依然是递归,如果在范围内就返回节点存的值,如果出了范围就返回 0。
最终代码