[SSL_CHX][2021-08-19]子矩阵求和

题目描述

给出一个m * n的矩阵a,矩阵元素a[i,j]小于1000,进行q次查询,每次查询给出子矩阵的4个边界(上下左右),求该子矩阵所有元素之和。

样例中第一个查询:1 3 1 2 表示从第1行到第3行,从第1列到第2列,对应的子矩阵是:

1 2
5 6
9 10

求和等于33

输入格式

第一行2个整数n, m,中间用空格分割,分别对应数组的行数n、列数m(1 <= m,n <= 100) 接下来n行,每行m个整数表示矩阵的内容a[i,j] 。(0 <= a[i,j] <= 1000) 接下来1行,一个数q,对应查询的数量。(1 <= q <= 1000) 接下来q行,每行4个整数,对应矩阵的上下左右边界u,d,l,r。(1 <= u <= d <= n, 1 <= l <= r <= m)

输出格式

输出共q行,对应q个询问的求和结果。

输入样例

3 4
1 2 3 4
5 6 7 8
9 10 11 12
3
1 3 1 2
1 2 1 3
1 3 1 3

输出样例

33
24
54

数据范围

解题思路

我们来看一下这个图:
在这里插入图片描述

那么最大的矩形前缀和就等于蓝的矩阵加上绿的矩阵,再减去重叠面积,最后加上小方块,即
sum[i][j]=sum[i][j−1]+sum[i−1][j]−sum[i−1][j−1]+a[i][j]
这样我们可以快速求出所有以 (0,0) 为左上角, (i,j) 为右下角的矩阵前缀和。

再来看一下这个图:
在这里插入图片描述
仍然利用上面给出的容斥的方法:矩阵 (E,H,I,F) 的和等于:

(A,G,I,C)−(A,G,H,B)−(A,D,F,C)+(A,D,E,B)
转换为题目对应的矩阵,就是:

sum[d][r]−sum[d][l−1]−sum[u−1][r]+sum[u−1][l−1];
因此对于任意一个子矩阵,我们都可以快速的对其求和。

Code

#include<bits/stdc++.h>
using namespace std;

int a[108][108],s;

int main()
{
	int n,m,q,x1,x2,y1,y2;
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			cin>>a[i][j];
		}
	}
	cin>>q;
	for(int i=1;i<=q;i++)
	{
		cin>>x1>>x2>>y1>>y2;
		s=0;
		for(int x=x1;x<=x2;x++)
		{
			for(int y=y1;y<=y2;y++)
			{
				s+=a[x][y];
			}
		}
		cout<<s<<endl;
	} 	
	return 0;
}

完成 *然后小伙就无了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值