差分陣列原理與其字首和的應用
看字你就應該知道,差分陣列存的是什麼了,即存的是每一項與前一項的差值。
例如這裡有 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] 的影響。
&n