# 【6-2】前綴和 & 後綴和
在以往的學習中,我們曾透過 `for` 迴圈來計算陣列中一段區間的元素總和
```cpp
int sum = 0;
for (int i = L; i <= R; ++i) {
sum += a[i];
}
```
* **時間複雜度**:每次都 $O(n)$
## 前綴和(Prefix Sum)
### 1. 定義
對長度為 `n` 的陣列 `a[0…n−1]`,建立 `prefix[]` 來儲存從開頭累加到每個位置的部分和:
$$
\text{prefix}[i] = \sum_{j=0}^{i} a_j
$$
```cpp
vector<int> prefix(n);
prefix[0] = a[0];
for (int i = 1; i < n; ++i) {
prefix[i] = prefix[i-1] + a[i];
}
// 範例:若 a = {5, 2, 4, 1, 3}
// 則 prefix = {5, 7, 11, 12, 15}
```
* **時間複雜度**:$O(n)$
### 2. 區間查詢
要算任意區間 `[L,R]` 的和,只要從 `prefix[R]` 扣掉不需要的前半段:
$$
\sum_{i=L}^{R} a_i =
\begin{cases}
\text{prefix}[R] - \text{prefix}[L-1], & L > 0,\\
\text{prefix}[R], & L = 0.
\end{cases}
$$
```cpp
// 查 a = {5,2,4,1,3} 中 [1,3] 的和:2+4+1 = 7
int sumLR = (L > 0 ? prefix[R] - prefix[L-1] : prefix[R]);
// sumLR = prefix[3] - prefix[0] = 12 - 5 = 7
```
* **時間複雜度**:$O(1)$
---
## 後綴和(Suffix Sum)
### 1. 定義
如果我們想從某個位置一路加到陣列末尾,就用後綴和 `suffix[]`,其定義和前綴和對稱:
$$
\text{suffix}[i] = \sum_{j=i}^{n-1} a_j
$$
```cpp
vector<int> suffix(n);
suffix[n-1] = a[n-1];
for (int i = n-2; i >= 0; --i) {
suffix[i] = suffix[i+1] + a[i];
}
// 範例:若 a = {5, 2, 4, 1, 3}
// 則 suffix = {15, 10, 8, 4, 3}
```
* **時間複雜度**:$O(n)$
### 2. 區間查詢
要算任意區間 `[L,R]` 的和,只要從 `suffix[L]` 扣掉不需要的後半段:
$$
\sum_{j=L}^{R} a_j =
\begin{cases}
\text{suffix}[L] - \text{suffix}[R+1], & R+1 < n,\\
\text{suffix}[L], & R = n-1.
\end{cases}
$$
```cpp
// 查 a = {5,2,4,1,3} 中 [1,3] 的和:2+4+1 = 7
int sumLR_suffix = (R+1 < n ? suffix[L] - suffix[R+1] : suffix[L]);
// = suffix[1] - suffix[4] = 10 - 3 = 7
```
* **時間複雜度**:$O(1)$
---
當一個陣列需要多次計算區間總和時,利用前綴和和後綴和的技巧,可以有效降低複雜度,當然,如果只需要計算一次的話,就不需要這麼麻煩了(不過題目很少出現只要計算一次總和的)。
---
聯絡方式:codecodefunny@gmail.com
最後編修時間:2025/08/03 子柚筆