字首和
一維字首和
一維字首和主要用於計算任意區間的元素和。
計算字首和
sum[i] = sum[i - 1] + a[i];
計算區間[l, r]的元素和
s = sum[r] - sum[l - 1];
二維字首和
二維字首和是一種用於快速計算二維陣列中任意子矩陣元素之和。
// 計算矩陣的字首和
s[x][y] = s[x - 1][y] + s[x][y - 1] - s[x - 1][y - 1] + a[x][y]
// 計運算元矩陣的和
sum = s[x2][y2] - s[x1 - 1][y2] - s[x2][y1 - 1] + s[x1 - 1][y1 - 1]
主要計算公式有以上兩種,計算矩陣的字首和即計算左圖中所有有顏色區域,其中s[x - 1][y]
是紅加綠色區域,s[x][y - 1]
是黃加綠色區域;計運算元矩陣的和即計算右圖中藍紫色區域。
差分
一維差分
一維差分是與一維字首和緊密相關,它主要用於對陣列進行區間更新操作,如需要對某個區間內的所有元素進行相同的增加或減少操作。
假設原陣列為 \(a\), 差分陣列為 \(b\)。
- 構造差分陣列
\(b[1] = a[1]\)
\(b[2] = a[2] - a[1]\)
……
\(b[i] = a[i] - a[i - 1]\)
……
\(b[n] = a[n] - a[n - 1]\)
- 區間更新操作
// 對區間 [l, r] 進行加 c
b[l] =+ c;
b[r + 1] -= c;
- 陣列恢復
在對差分陣列 \(b\) 進行了一系列區間更新操作後,透過計算字首和來恢復原陣列 \(a\),即 \(a[i] = a[i − 1] + b[i]\)。
二維差分
二維差分,類似於一維差分,是一個二維陣列的子矩陣進行統一的增加或減少操作。
假設原陣列為 \(a\), 差分陣列為 \(b\)。
對上圖中的綠色區域加c。
void insert(int x1, int y1, int x2, int y2, int c)
{
b[x1][y1] += c;
b[x2 + 1][y1] -= c;
b[x1][y2 + 1] -= c;
b[x2 + 1][y2 + 1] += c;
}
insert(i, j, i, j, a[i][j]); // 記得構建差分陣列
insert(x1, y1, x2, y2, c); // 差分陣列加c
恢復原陣列操作與二維字首和類似
a[i][j] = b[i][j] + a[i − 1][j] + a[i][j − 1] − a[i − 1][j − 1]
//or 直接用b陣列儲存
b[i][j] += b[i - 1][j] + b[i][j - 1] - b[i - 1][j - 1]