前缀和
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;
}