2901: 矩阵求和
Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 512 Solved: 289
[Submit][Status][Discuss]
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
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。
388
【数据规模和约定】
对30%的数据满足,n <= 100。
对100%的数据满足,n <= 2000,m <= 50000,输入数据中矩阵元素 < 100,a,b,c,d <= n。
不妨设a<=c,b<=d,那么 ∑i=ac∑j=bdR[i][j]=∑i=ac∑j=bd∑k=1nP[i][k]⋅Q[k][j]=∑k=1n(∑i=acP[i][k])⋅(∑j=bdQ[k][j])=∑k=1n(sumP[c][k]−sumP[a−1][k])(sumQ[k][d]−sumQ[k][b−1])
时间复杂度O(nm),可过。
#include<cmath>
#include<ctime>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<iomanip>
#include<vector>
#include<string>
#include<bitset>
#include<queue>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
}
void print(ll x)
{if(x<0)x=-x,putchar('-');if(x>=10)print(x/10);putchar(x%10+'0');}
const int N=2010;
ll suma[N][N],sumb[N][N];
int main()
{
int n=read(),m=read();
register int i,j;
for(i=1;i<=n;++i)for(j=1;j<=n;++j)
{suma[i][j]=suma[i-1][j]+read();}
for(i=1;i<=n;++i)for(j=1;j<=n;++j)
{sumb[i][j]=sumb[i][j-1]+read();}
register int a,b,c,d;
while(m--)
{
ll res=0;
a=read();b=read();c=read();d=read();
if(a>c)swap(a,c);if(b>d)swap(b,d);
for(i=1;i<=n;++i)
res+=(sumb[i][d]-sumb[i][b-1])*(suma[c][i]-suma[a-1][i]);
print(res);puts("");
}
return 0;
}
/*
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
661
388
*/