差分陣列原理與其字首和的應用

大頭衝鋒車丶發表於2019-08-12

看字你就應該知道,差分陣列存的是什麼了,即存的是每一項與前一項的差值。

例如這裡有 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] 的影響。

 

相關文章