差分数组原理与其前缀和的应用

看字你就应该知道,差分数组存的是什么了,即存的是每一项与前一项的差值。

例如这里有 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] 的影响。

原文地址:https://www.cnblogs.com/Absofuckinglutely/p/11342005.html