题解: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
posted @ 2026-02-20 22:43  团爸讲算法  阅读(9)  评论(0)    收藏  举报