子矩阵的和(二维前缀和)
一、算法描述
上一篇文章介绍了一维前缀和,也就是一个数组的前n
项和,这篇文章来介绍一下什么是二维前缀和。
含义
- 一维的是前
n
项的和,那么二维的情况下,表示的则是与左上角形成的矩形和。
怎么求
-
一维的递推关系式是
s[i] = s[i - 1] + a[i];
,我们根据含义来思考二维的递推关系式,读者可以在草稿纸上画一个矩形来更好的理解。 -
表示的是 这个位置与左上角形成的矩形和, 表示的是比 少一行的矩形和, 表示的是比 少一列的矩形和。 -
用
得到的就是 ,但是少了一个 ,同时多了一个 与左上角形成的矩形和,即 。 -
综上可以得到求得
的递推关系式为:s[i][j] = s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1] + a[i][j];
,读者应在草稿纸上自己推理,不要纯靠记忆。
怎么用
-
一维前缀和的用法在
的时间复杂度内求得 的区间和,那么二维前缀和则是在 的时间复杂度内求得 到 这个区域的矩形和。 -
显然我们要用
这块大面积来减去其他的面积,那么需要减去哪些部分呢?大家自行在草稿纸上推演,计算如下:s[x2][y2] - s[x2][y1 - 1] - s[x1 - 1][y2] + s[x1 - 1][y1 - 1];
,根据含义来思考如何推算。
二、题目描述
输入一个
对于每个询问输出子矩阵中所有数的和。
输入格式
第一行包含三个整数
接下来
接下来
输出格式
共
数据范围
输入样例:
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
三、题目来源
四、源代码
#include <iostream>
using namespace std;
const int N = 1010;
int n, m, q;
int a[N][N], s[N][N];
int main()
{
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)
s[i][j] = s[i][j - 1] + s[i - 1][j] - s[i - 1][j - 1] + a[i][j];
while (q -- )
{
int x1, y1, x2, y2;
cin >> x1 >> y1 >> x2 >> y2;
cout << s[x2][y2] - s[x2][y1 - 1] - s[x1 - 1][y2] + s[x1 - 1][y1 - 1] << endl;
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!