传送门:线段树也不过如此
这标准线段树模板题,但是多年没碰线段树,现在已经基本不会写了T^T
首先是创建线段树。
线段树是个满二叉树,如果从长度为n的数组上生成线段树,那么树节点个数m满足
m ≤ 2 q + 1 − 1 m \le 2^{q+1} - 1 m≤2q+1−1
其中 2 q > n ∧ 2 q − 1 < n 2^q > n \land 2^{q-1} < n 2q>n∧2q−1<n
此外对于满二叉树来说,假设当前节点编号为n,则left node编号为 2 n 2n 2n,right node编号为 2 n + 1 2n+1 2n+1,ancestor编号为 n / 2 n/2 n/2。借助这些性质可以实现在数据中存储树节点时快速访问。
应用到这个题来说,需要建两棵线段树:一颗记录行,一颗记录列。根据题意,初始状态下没有rock,所以叶结点val都是0
然后是线段树更新:首先到叶结点,更新叶结点数据;然后,回溯的时候更新ancestor中记录的区间的值。
对于这个题来说,行线段树中非叶结点中记录的是从left行到right行中,一行最少有几个rock。回溯时根据left和right节点的值更新区间最小值。列线段树同理。
最后是查询。首先要明确的一点是,查询的区间 x x x始终是数组的子区间 x ⊂ [ 1 , n ] x\subset [1,n] x⊂[1,n],所以查询的时候只考虑Ⅰ情况即可
具体到每个非叶结点所代表的区间查询时,借助中间变量mid来判断下一步需要查询的区间。设需要查询的区间为 [ l , r ] [l,r] [l,r],非叶结点代表区间 [ L , R ] [L,R] [L,R],非叶节点代表区间的区间中点为 m i d mid mid
如果 m i d < l mid < l mi</