淺談差分數組
本篇隨筆簡單講解一下信息學奧林匹克競賽中差分算法及差分數組的應用。讀者在閱讀本隨筆前最好擁有一些基本的算法競賽的知識,了解如前綴和、數組等基本數據結構。這將會使你的閱讀體驗變得更佳舒適。
差分數組的定義
來看一個例子:
原數組\(a:5,8,4,3,15\)
差分數組 \(b:5,3,-4,-1,12\)
發現了什么沒?
差分數組就是原數組對應項和它前面那項的差值。
這里會有一個性質:
原數組中的第\(i\)項就等於:
這是顯然的。
差分前綴和
還是先來看例子:
原數組:\(a:5,8,4,3,15\)
它的前綴和數組:\(c:5,13,17,20,35\)
它的差分數組:\(b:5,3,-4,-1,12\)
它的差分前綴和(就是差分數組的前綴和):\(d:5,8,4,3,15\)
我們發現,差分前綴和就是原數組。這個性質可以通過上面的性質\(\sum_{j=1}^{j=i}b[j]\)得出。
差分數組的應用
看起來差分並沒有那么難。但是差分思想博大精深。
我們看一道題:
對一個區間,我們每一次操作將\([l,r]\)這段區間上的所有數加上\(delta\)。
最后查詢某一個區間的和。
如果考慮暴力修改的話,時間復雜度是\(O(nm)\)的。過不了。
那么我們考慮線段樹和樹狀數組差分。
根據我們剛剛研究出來的差分的性質,我們發現,因為我們差分數組只維護了相鄰兩個元素的差值,但是因為是區間修改,所以這段區間內部相鄰元素的差值其實是沒有被改變的。也就是說,差分數組中發生改變的元素僅是第一個元素和最后一個元素+1(這里好好理解一下)
也就是說,我們只需要把差分數組\(b\)中的\(b[l],b[r+1]\)加上\(delta\),就可以做到在\(O(2)\)的時間進行區間修改。
但是!!
剛剛把“最后查詢”打上黑體是有原因的。因為如果在操作中多次進行查詢操作,就需要多次統計,而差分只是優化了修改的復雜度,查詢的復雜度還是\(O(n)\)的,所以如果是多次查詢的話,就需要線段樹、樹狀數組等數據結構優化了。