AcWing 796. 子矩阵的和 解题思路及代码

先贴个题目:

以及原题链接: 796. 子矩阵的和 - AcWing题库icon-default.png?t=N7T8https://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)是已经处理好数据的呢,我们在计算时会使用二重循环,自上而下,自左到右进行计算,不难看出,当计算到当前格子时,其他区块都已经进行数据处理,所以可以得出公式:a[x,y]=a[x-1,y]+a[x,y-1]-a[x-1,y-1]+a[x,y]

而如果要计算一块区域的和的话,我们不妨再画一张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)之间的和,那么sum=a[x2][y2] - a[x2 - x1-1][y2] - a[x2][y2 - y1-1] + a[x2 - x1-1][y2 - y1-1]

 这题就很好解决了。

#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刷题记录

  • 7
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值