本文最后更新于 39 天前,其中的信息可能已经过时,如有错误请发送邮件到 wsryhc@qq.com
前缀和是为了方便计算在一个数组内的区间中的和,同时也包含二维数组计算。
需要两个数组,一个是原数组,一个是记录前缀和的数组。
假设原数组为 a,记录数组为 b,那么 b [0]=a [0];b [1]=b [0]+a [1]; 数组 b 中的第 i 个位置就是记录数组 a 中 0~i 的和。
加入需要求 a [i]+…+a [j],只需要计算 b [j]-b [i-1],就可以求出答案。
| int a[5]={1,2,3,4,5},b[5]; |
| b[0]=a[0]; |
| for(int i=1;i<5;i++){ |
| b[i]=b[i-1]+a[i]; |
| } |
也是同时需要两个数组,一个为原数组,一个为记录前缀和数组。
注:计算时,在加上了 [i-1][j] 和 [i][j-1] 后,[i-1][j-1] 项会被重复加一次,需要减掉。
| #include <iostream> |
| using namespace std; |
| const int N = 1010; |
| int n, m, q; |
| int s[N][N]; |
| int main() |
| { |
| scanf("%d%d%d", &n, &m, &q); |
| for (int i = 1; i <= n; i ++ ) |
| for (int j = 1; j <= m; j ++ ) |
| scanf("%d", &s[i][j]); |
| for (int i = 1; i <= n; i ++ ) |
| for (int j = 1; j <= m; j ++ ) |
| s[i][j] += s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1]; |
| while (q -- ) |
| { |
| int x1, y1, x2, y2; |
| scanf("%d%d%d%d", &x1, &y1, &x2, &y2); |
| printf("%d\n", s[x2][y2] - s[x1 - 1][y2] - s[x2][y1 - 1] + s[x1 - 1][y1 - 1]); |
| } |
| return 0; |
| } |
| |
| 作者:yxc |
| 链接:https: |
| 来源:AcWing |
| 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 |
若有一个数组,现在需要同时对他们一段区间全部进行加减一个数,差分算法只需要对于头尾进行修改,就可以修改区间全部数。
还是同样需要一个原数组,一个记录差分的数组。
原数组 a,记录数组 b。a [0]==b [0];后面 b [i]=a [i]-a [i-1]。在下一次需要进行输出的时候,只需要从 b [0] 开始每次加上下一个 b 数组就可以输出全部的数字,如果需要对于 [i,j] 区间全部加或者减一个数,只需要在 b [i] 加或者减那个数,然后在 b [j+1] 上补回来,这样就不需要全部进行操作。
| int a[5]={1,2,3,4,5}; |
| int b[5]; |
| b[0]=a[0]; |
| for(int i=1;i<5;i++){ |
| b[i]=a[i]-a[i-1]; |
| } |
| b[0]-=10; |
| b[3]+=10; |
| for(int i=0,j=0;i<5;i++){ |
| j+=b[i]; |
| printf("%d ",j); |
| } |
同样,只需要对于四个角的数字进行修改就可以修改区间矩阵的全部数字,需要进行反向的思维,一开始数组 b 为空的,每次输入就是插入在一个数字的范围加上输入的数,最后输出按照前缀和输出。
| #include<iostream> |
| #include<cstdio> |
| using namespace std; |
| const int N = 1e3 + 10; |
| 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 n, m, q; |
| cin >> n >> m >> q; |
| for (int i = 1; i <= n; i++) |
| for (int j = 1; j <= m; j++) |
| cin >> a[i][j]; |
| for (int i = 1; i <= n; i++) |
| { |
| for (int j = 1; j <= m; 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 <= n; i++) |
| { |
| for (int j = 1; j <= m; j++) |
| { |
| b[i][j] += b[i - 1][j] + b[i][j - 1] - b[i - 1][j - 1]; |
| } |
| } |
| for (int i = 1; i <= n; i++) |
| { |
| for (int j = 1; j <= m; j++) |
| { |
| printf("%d ", b[i][j]); |
| } |
| printf("\n"); |
| } |
| return 0; |
| } |
| |
| 作者:林小鹿 |
| 链接:https: |
| 来源:AcWing |
| 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 |