题目描述
给出一个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;
}