看字你就应该知道,差分数组存的是什么了,即存的是每一项与前一项的差值。
例如这里有 A[] 数组:
A[] = 0 1 3 8 4 5 7 ( 下标从 0 开始,A[0] 为 0 )
根据 D[i] = A[i] - A[i-1],我们可以得到 D[] 数组:
D[] = 0 1 2 5 -4 1 2
直观的,我们可以看出:
D[0] + D[1] = A[1] = 1
D[0] + D[1] + D[2] = A[2] = 3
D[0] + D[1] + D[2] + D[3] = A[3] = 8
.........................................................
嗯,所以得到的 D[] 数组,再求一下前缀和,就可以知道 A[i] 的值了。
那这样有什么好处呢?
这样就可以 O(1) 处理区间更新,然后就能很快的求解单点查询了
还是上面的例子,现在我们使区间 [3,5] 全部加上 2
然后你这样想:如何处理 D 数组,使得:
D[1] + D[2] + D[3] = A[3] + 2
D[1] + D[2] + D[3] + D[4]= A[4] + 2
D[1] + D[2] + D[3] + D[4] + D[5] = A[5] + 2
为了满足上面三个式子,我们应该使: D[1] += 2 或者 D[2] += 2 或者 D[3] += 2
然而如果是 D[1] += 2 或者 D[2] += 2 的话,那我现在用 D 数组求 A[1] 或者 A[2] 的话,不就错了吗?
所以我只能使得 D[l] += 2 ,即这里的 D[3] += 2 ,这样我即可以 O(1)修改区间 [3,5],又不会使 1 ~ l 的运算出错。
同样!为了保证用 D 数组求 A[r+1] A[r+2] ..... 时不出错,我们必须消除 加 2 对他们的影响,因为 只是 [3,5] 加了 2 。
跟上面的思路一样,必须消除影响,即需要在 D[r] 或者 D[r+1] 、D[r+2] 的时候减去 2 ,这样前缀和时,加 2 减 2 消掉了,不会给后面造成影响。
那么如果 D[r] -= 2 ,算 A[r] 的时候就错了,因为这相当于 A[r] 没有更新 加 2 。
如果 D[r + 2] 减 2 的话,会使得算 A[r + 1] 的时候算错,因为这相当于 A[r + 1] 加了 2 。在 D[r + 3] 、D[r + 4] ......减 2 同理,都不行。
综上:我们需要在 D[l] += k ,D[r + 1] -= k ,以便保证算 [l,r] 的时候不会错,也消除了算[1,l] 和 [r + 1,n] 的影响。