题解:AcWing 796 子矩阵的和

【题目来源】

AcWing:796. 子矩阵的和 - AcWing题库

【题目描述】

输入一个 \(n\)\(m\) 列的整数矩阵,再输入 \(q\) 个询问,每个询问包含四个整数 \(x_1,y_1,x_2,y_2\),表示一个子矩阵的左上角坐标和右下角坐标。

对于每个询问输出子矩阵中所有数的和。

【输入】

第一行包含三个整数 \(n,m,q\)

接下来 \(n\) 行,每行包含 \(m\) 个整数,表示整数矩阵。

接下来 \(q\) 行,每行包含四个整数 \(x_1,y_1,x_2,y_2\),表示一组询问。

【输出】

\(q\) 行,每行输出一个询问的结果。

【输入样例】

3 4 3
1 7 2 4
3 6 2 8
2 1 2 3
1 1 2 2
2 1 3 4
1 3 3 4

【输出样例】

17
27
21

【解题思路】

image

【算法标签】

《AcWing 796 子矩阵的和》 #前缀和#

【代码详解】

#include <bits/stdc++.h>
using namespace std;const int N = 1010;  // 定义二维数组最大尺寸int n, m, q;        // n: 行数, m: 列数, q: 查询次数
int a[N][N];        // 存储原始二维数组
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", &a[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] + a[i][j];}}// 处理每个查询while (q--){int x1, y1, x2, y2;  // 查询子矩阵的左上角和右下角坐标scanf("%d%d%d%d", &x1, &y1, &x2, &y2);// 计算子矩阵和公式:右下角前缀和 - 上方前缀和 - 左方前缀和 + 左上角前缀和printf("%d\n", s[x2][y2] - s[x2][y1-1] - s[x1-1][y2] + s[x1-1][y1-1]);}return 0;
}

【运行结果】

3 4 3
1 7 2 4
3 6 2 8
2 1 2 3
1 1 2 2
17
2 1 3 4
27
1 3 3 4
21