字首和與差分 演算法詳解

2022-04-09 09:58:26 字數 1599 閱讀 9759

1 . 字首和

其實可以把它理解為數學上的數列的前n項和(對於乙個一維陣列的字首和)。

我們定義對於乙個陣列a的字首和陣列s,s[i] = a[1]+a[2]+...+a[i].

2 . 二維字首和

與一維字首和類似,設s[i][j]表示所有a[i'][j']的和。(1≤i'≤i,1≤j'≤j)

有一點像「矩形的面積」那樣,把一整塊區域的值都加起來。

3 . 字首和的用途

一般用來求區間和。

對於一維情況,現在我給出乙個數列a,要求你回答m次詢問,每次詢問下標j到k的和。樸素的做法顯然是對於每次詢問都執行一次相加操作,然後輸出結果。這樣做是正確的,但是當m過大時就會導致計算次數過多而有可能超時。

超時的原因一目了然,重複計算。那麼我們應該怎麼改進這個方法呢?想象一下,我們如果先提前算好了每乙個位置的字首和,然後用s[k]-s[j],結果不就是我們這次詢問的答案嗎?這樣便會使計算量大大減小。

對於二維的區間和,也是類似的。

我們借助這個研究一下。假設在這個矩陣(二維陣列)中,我們要求和的是上圖中紅色區域。現在我們已經預處理出了所有點的字首和,現在給定兩個點(x1,y1),(x2,y2),我們要求 以這兩個點連線為對角線的乙個子矩陣的數值之和。暴力做法直接挨個加這個我就不再多說了,反正早晚都得tle,我們重點考慮用字首和的快速做法。

首先我們可以把s[x2][y2]求出來,它代表整個大矩形的字首和,然後我們分別減去它左邊多出來的一塊的字首和和下邊多出來一塊的字首和,這樣就是最終答案了?

不是!這不是最終答案。可以發現,在我們剪掉這兩個多出的區域時,下邊的一小塊被減了兩次,但減兩次顯然是不合理的,我們應該加回來。。

所以對於一次的查詢答案ans應該等於s[x2][y2]-s[x2][y1-1]-s[x1-1][y2]+s[x1-1][y1-1]

這個二維字首和也稱差分序列。

4 . 用差分實現區間操作

給定乙個長度為n的數列a,要求支援操作add(l,r,k)表示對a[l]~a[r]的每個數都加上k。並求修改後的序列a。

暴力做法顯然,tle,下乙個。

我們考慮用差分的做法。這裡 需要乙個輔助陣列c,c用來記錄某乙個位置上的總改變量。c[i]表示的是i~n這些元素都加上c[i]這個數。我們對[l,r]區間進行加值操作,在c[l]處加乙個k,在c[r+1]處就減去乙個k。最後求序列的每個位置變成了多少,只需要求一下c陣列的字首和,然後和原陣列按位相加就好。

這個結論的證明我不是太會。。呃記住它是對的就好啦。。

對於二維的情況,乙個n*m的矩陣,要求支援操作add(x1,y1,x2,y2,a),表示對於以(x1,y1)為左下角,(x2,y2)為右上角的矩形區域,每個元素都加上a。要求修改後的矩陣。

我們的做法和一維類似。用陣列c儲存總改變量。在c[x1][y1]處加上a,在c[x2+1][y1]和c[x1][y2+1]處減a,在c[x2+1][y2+1]再加上a。最後(i,k)位置上的數值就是c陣列在(i,k)位置的字首和。

字首和,差分演算法

其實可以把它理解為數學上的數列的前n項和 對於乙個一維陣列的字首和 我們定義對於乙個陣列a的字首和陣列s,s i a 1 a 2 a i 與一維字首和類似,設s i j 表示所有a i j 的和。1 i i,1 j j 有一點像 矩形的面積 那樣,把一整塊區域的值都加起來。一般用來求區間和。對於一維...

序列演算法 字首和與差分

一般的字首和是對於陣列的求和,即對陣列的某一子陣列進行求和,即sum i,j sum i sum j 1 不僅如此字首和還能用於任何含可逆運算的運算子包括異或xor。上述的子陣列和的問題屬於陣列固定,大量訪問的問題優化。下面給出乙個大量做區間加的情況 給定乙個序列a 有很多次操作,每個操作形如 a ...

字首和與差分

數列的字首和 sum i 表示a 1 a i 的和 用處1 求i j的和sum j sum i 1 用處2 區間修改。設定乙個change陣列。當區間 i,j 上要加k時,我們令change i k,令change j 1 k。如果我們對change陣列求字首和的話,字首和sum change i ...