先贴个题目:
以及原题链接: 796. 子矩阵的和 - AcWing题库https://www.acwing.com/problem/content/798/
先讲讲思路:前缀和的代码模板题,只不过一维变成二维,而计算的方法也发生了变化,在这边举个例子,要求前面所有格子的和,先画一个3*3的表格
(0,0) | (0,1) | (0,2) |
(1,0) | (1,1) | (1,2) |
(2,0) | (2,1) | (2,2) |
可以看出,如果要让(2,2)代表前面所有区块的和,可以看成是已经处理好前缀和的(1,2)+(2,1)-(1,1)+还未处理数据的(2,2)区域,简单的容斥原理,然后怎么保证计算时(1,2),(2,1),(1,1)是已经处理好数据的呢,我们在计算时会使用二重循环,自上而下,自左到右进行计算,不难看出,当计算到当前格子时,其他区块都已经进行数据处理,所以可以得出公式:。
而如果要计算一块区域的和的话,我们不妨再画一张3*3的表格
(0,0) | (0,1) | (0,2) |
(1,0) | (1,1) | (1,2) |
(2,0) | (2,1) | (2,2) |
如果要求(1,1)-(2,2)这四块区域的和,那么依然根据容斥原理,在已经计算好前缀和的情况下,不难得出结论: 如果要求a(x1,y1)与b(x2,y2)之间的和,那么
这题就很好解决了。
#include <iostream>
#include<cstring>
using namespace std;
int main()
{
int n, m, q;
cin >> n >> m >> q;
int **a = new int *[n + 10];
int **b = new int *[n + 10];
memset(a, 0, sizeof(a));
memset(b, 0, sizeof(b));
for (int i = 0; i < n + 10; ++i)
{
a[i] = new int[m + 10];
b[i] = new int[m + 10];
}
for (int i = 1; i < n+1; ++i)
for (int j = 1; j < m+1; ++j)
cin >> a[i][j];
for (int i = 1; i < n+1; ++i)
for (int j = 1; j < m+1; ++j)
b[i][j] = b[i - 1][j] + b[i][j - 1] - b[i - 1][j - 1] + a[i][j];
for (int i = 0; i < q; ++i)
{
int x1, y1, x2, y2;
cin >> x1 >> y1 >> x2 >> y2;
int sum;
sum = b[x2][y2] - b[x1 - 1][y2] - b[x2][y1 - 1] + b[x1 - 1][y1 - 1];
cout << sum << endl;
}
return 0;
}
没啥难度,小技巧从(1,1)开始写,可以不用特判。
(这两天有点忙,题解积了几天了。。。)
by————2024.2.3刷题记录