前缀和
1.一维的795. 前缀和 - AcWing题库
前缀和公式
s[i] = a[1] + a[2] + a[3] + ... + a[i] 即
s[i] = s[i-1] + a[i]
#include<iostream>
using namespace std;
const int N = 1e5 + 10;
int a[N], s[N];
int main(){
int m, n;
cin >> n >> m;
for(int i = 1; i <= n; i++)
cin >> a[i];
// 初始化前缀和数组
for(int i = 1; i <= n; i++)
s[i] = s[i-1] + a[i];
while(m--) {
int l, r;
cin >> l >> r;
// 减去左边多余的
cout << s[r] - s[l-1] << endl;
}
return 0;
}
注意原数组与前缀和数组都要从1开始存,避免边界问题
2.二维的796. 子矩阵的和 - AcWing题库797. 差分 - AcWing题库
二维前缀和公式
s[i][j] = s[i-1][j] + s[i][j-1] - s[i-1][j-1] + a[i][j]
#include<iostream>
using namespace std;
const int N = 1e3 + 10;
int a[N][N], s[N][N];
int main(){
int m, n, q;
cin >> m >> n >> q;
for(int i = 1; i <= m; i++)
for(int j = 1; j <= n; j++)
cin >> a[i][j];
// 初始化二维前缀和数组
for(int i = 1; i <= m; i++)
for(int j = 1; j <= n; j++)
s[i][j] = s[i-1][j] + s[i][j-1] - s[i-1][j-1] + a[i][j];
int x1, x2, y1, y2;
while(q--) {
cin >> x1 >> y1 >> x2 >> y2;
// 输出对应结果
cout << s[x2][y2] - s[x1-1][y2] - s[x2][y1-1] + s[x1-1][y1-1] << endl;
}
return 0;
}
差分
3.一维的797. 差分 - AcWing题库
#include<iostream>
using namespace std;
const int N = 1e5 + 10;
int a[N], b[N];
void insert(int l, int r, int c){
b[l] += c;
b[r+1] -= c;
}
int main(){
int m, n;
cin >> n >> m;
for(int i = 1; i <= n; i++)
cin >> a[i];
// 初始化差分数组
for(int i = 1; i <= n; i++)
insert(i, i, a[i]);
int l, r, c;
while(m--) {
cin >> l >> r >> c;
insert(l, r, c);
}
// 还原数组
for(int i = 1; i <= n; i++)
b[i] += b[i-1];
for(int i = 1; i <= n; i++)
cout << b[i] << " ";
return 0;
}
差分数组用来间接表示这个序列,当对原数组的区间进行修改时,只需要对差分数组的起始、结尾位置分别进行一次修改就好
差分数组中的元素就是这个元素跟它的前一个元素的差值,比如
原数组:[1, 2, 2, 1, 2, 1]
差分数组:[1, 1, 0, -1, 1, 1]
可以直观的看到对差分数组进行前缀和操作就可以得到原数组
想象差分数组中的每个元素代表了一段“坡度”,前缀和则是沿着这些坡度从起点走到当前位置的累积高度变化。最终,这个累积变化量正是原序列中相应位置的值。
4.二维的798. 差分矩阵 - AcWing题库
#include<iostream>
using namespace std;
const int N = 1010;
int a[N][N], b[N][N];
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;
}
int main(){
int m, n, q;
cin >> m >> n >> q;
for(int i = 1; i <= m; i++)
for(int j = 1; j <= n; j++)
cin >> a[i][j];
for(int i = 1; i <= m; i++)
for(int j = 1; j <= n; j++)
insert(i, j, i, j, a[i][j]);
while(q--){
int x1, y1, x2, y2, c;
cin >> x1 >> y1 >> x2 >> y2 >> c;
insert(x1, y1, x2, y2, c);
}
for(int i = 1; i <= m; i++)
for(int j = 1; j <= n; j++)
b[i][j] = b[i][j] + b[i-1][j] + b[i][j-1] - b[i-1][j-1];
for(int i = 1; i <= m; i++){
for(int j = 1; j <= n; j++){
cout << b[i][j] << " ";
}
cout << endl;
}
return 0;
}