【BZOJ2901】矩阵求和

Description

给出两个n*n的矩阵,m次询问它们的积中给定子矩阵的数值和。

Input

第一行两个正整数n,m。
接下来n行,每行n个非负整数,表示第一个矩阵。
接下来n行,每行n个非负整数,表示第二个矩阵。
接下来m行,每行四个正整数a,b,c,d,表示询问第一个矩阵与第二个矩阵的积中,以第a行第b列与第c行第d列为顶点的子矩阵中的元素和。

Output

对每次询问,输出一行一个整数,表示该次询问的答案。

Sample Input

3 2
1 9 8
3 2 0
1 8 3
9 8 4
0 5 15
1 9 6
1 1 3 3
2 3 1 2

Sample Output

661
388
【数据规模和约定】
对30%的数据满足,n <= 100。
对100%的数据满足,n <= 2000,m <= 50000,输入数据中矩阵元素 < 100,a,b,c,d <= n。

 时间限制20s

题解:一看这道题,自然想到能不能用前缀和直接搞,但是这样做可以吗?答案是可以的

 

时间复杂度O(nm),还有此题必须加读入优化

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
const int maxn=2010;
int n,m;
long long ans;
int sx[maxn][maxn],sy[maxn][maxn];
int rd()
{
	int ret=0;	char gc=getchar();
	while(gc<'0'||gc>'9')	gc=getchar();
	while(gc>='0'&&gc<='9')	ret=ret*10+gc-'0',gc=getchar();
	return ret;
}
int main()
{
	n=rd(),m=rd();
	int i,j,a,b,c,d;
	for(i=1;i<=n;i++)	for(j=1;j<=n;j++)	sx[i][j]=sx[i-1][j]+rd();
	for(i=1;i<=n;i++)	for(j=1;j<=n;j++)	sy[i][j]=sy[i][j-1]+rd();
	for(i=1;i<=m;i++)
	{
		a=rd(),b=rd(),c=rd(),d=rd(),ans=0;
		if(a>c)	swap(a,c);
		if(b>d)	swap(b,d);
		for(j=1;j<=n;j++)	ans+=(long long)(sx[c][j]-sx[a-1][j])*(sy[j][d]-sy[j][b-1]);
		printf("%lld\n",ans);
	}
	return 0;
}
posted @ 2017-03-31 19:09  CQzhangyu  阅读(300)  评论(0编辑  收藏  举报