@TOC
区间查询与修改的总体思想(以入门的角度理解)
’‘’
讲的不好勿喷。
‘’‘
树状数组单纯地最多只设计区间影响,没有涉及区间影响后的相加的和。
如何add(l, +d), add(r, -d) =>可以知道+d给了l到r的区间中的值一个影响,但无法构造出得到[l, r]中造成影响+d的和。
那么就不能实现了吗,肯定不。
如果能够构造出,当在l+5 (l +5< r)的点内的+d影响和为+d * (l + 5 - l) [!!]。
这不就有方法了吗,只要我求那个点,就在对应位置的影响中*x,看看情况如何。
【!!!】x,l,r都是表示都是从0开始到哪里的长度,且这里都是求前缀和。
1.当 x<l时,无影响(都没遍历到那个影响中)
2.当l <= x && x < r时,
+d * x明显多了(l - 1)个+d。
3.当x >= r时,
那个点同时受到有+d 和 -d影响, +d * x + -d * x = 0.
什么情况怎么少了一个(r - l)个+d。
怎么不行了,有问题呀,不急再看看。
(其中l-1不好看,我改成在x点多所有影响*(x + 1),如果 不改,按下面的思想也是对的)
所以有:
1.当 x<l时,无影响(都没遍历到那个影响中)
2.当l <= x && x < r时,
+d * (x + 1)明显多了l个+d。
3.当x >= r时,
那个点同时受到有+d 和 -d影响, +d * x + -d * x = 0, 什么情况怎么少了一个(r - l)个+d。
要实现在[l,r)内要-(+d * (l -1)),在[r, +无穷)要+(r-l)* +d
=> 可以说在在[l, +无穷)要- (+d * l),在[r, +无穷)要 +d * r
=> 什么情况,这不是相当于在[l, +无穷)给他一个(-d*l)的影响,在[r, +无穷)给他一个+ d*r的影响。
=>具体带码实现呢?add(l, +d * l), add(r, -d * r);
/*
注意有些代码是add(r+1, -d * (r +1))这里的(r+1)与r点意思都是相同的。
只是书写时的形式的不同,如(0 + 1) 与 1点区别。
*/
综合起来就是
tr1 add(l, +d), add(r, -d)
tr2 add(l, +d * l), add(r, -d * r)
prefix_sum(x): sum(tr1, x) * (x + 1) - sum(tr2, x);
//求前缀和的影响和,相那什么本身值a[i],就别放进来了,单独列一个前缀数组sum_a[i]不香吗。
prefix_sum(l): sum(tr1, l) * (l + 1) - sum(tr2, l);
prefix_sum(r): sum(tr1, r) * (r + 1) - sum(tr2, r);
prefix_sum(r) - prefix_sum(l)