## 前綴和
功能:可求出任意區間的總和
經典問題:
給一個長度為N的序列a,有Q筆詢問,第i筆詢問為求[l,r]的總和
暴力解
針對每一次查詢都去做加總
複雜度為O(NQ)
```cpp
#include <iostream>
using namespace std;
int main(){
int n;
cin >> n;
int a[n+1];
for(int i = 1; i <= n; i++) cin >> a[i];
int q, l, r;
cin >> q;
while(q--){
cin >> l >> r;
int sum = 0;
for(int i = l; i <= r ;i++) sum += a[i];
cout << sum << "\n";
}
}
```
sum[i] = 陣列前i項的和
sum[i] = a[1] + a[2] + … + a[i]
與前項關係 -> sum[i] = sum[i-1] + a[i]
區間和 [l, r]:a[l] +a[l+1] + ... + a[r]
= sum[r]-sum[l-1] (要保留a[l]所以-1)
前綴和預處理
O(N+Q)
```cpp
#include <iostream>
using namespace std;
int main(){
int n;
cin >> n;
int a[n+1], sum[n+1]={0};
for(int i=1; i<=n; i++) cin >> a[i];
for(int i=1; i<=n; i++) sum[i] = sum[i-1] + a[i];
int q, l, r;
cin >> q;
while(q--){
cin >> l >> r;
cout << sum[r] - sum[l-1] << "\n" ; //區間和
}
}
```
練習題
zj:e339
帶修改的版本->BIT,線段樹
---
### 二維前綴和
待補
---
## 差分
可以把它想成前綴和的逆運算
定義:任意兩個相鄰值相減形成差的簡稱
如序列{1、5、6}的差分序列為{4、1}
用途:在區間 [l, r] 加上一個數字v
經典問題:
給一個長度為N的序列a,有Q筆改值,求第K項
實作:
a -> 前綴和數列, b -> 差分數列
b[l] += v; //b[0~l] 加上v
b[r+1] -= v; //b[r+1~n] 減去v (b[r] 仍保留v)
a[i] = b[0] + b[1] + b[2] + … + b[i](前綴和)
所以 b[i] = a[i] – a[i-1]
在 b[l] 加上 v,b[r+1] 減去 v
最後再從 0 跑到 n 使 b[i] += b[i-1]
這樣b 是一個在某區間加上v的前綴和
```cpp
#include <iostream>
using namespace std;
int a[1000], b[1000];
//a: 前綴和數列, b: 差分數列
int main(){
int n, l, r, v ,q;
cin >> n;
for(int i=1; i<=n; i++){
cin >> a[i];
b[i] = a[i] - a[i-1]; //建構差分數列
}
cin >> l >> r >> v >> q;
b[l] += v;
b[r+1] -= v;
for(int i=1; i<=q; i++){
b[i] += b[i-1];
}
cout << b[q] ;
```
練習
zj:e340