输入挂(bzoj 2901: 矩阵求和)

很少用输入挂,以为不超时就好了,但是这题貌似不用过不去啊

只好拿出来用了,当个模板

原理是用getchar()读入会比用scanf快一些

int Read()
{
	int x = 0, f = 1;
	char ch;
	ch = getchar();
	while(ch<'0' || ch>'9')
	{
		if(ch=='-')  f = -1;
		ch = getchar();
	}
	while(ch>='0' && ch<='9')
		x = x*10+ch-'0', ch = getchar();
	return x*f;
}


2901: 矩阵求和

Time Limit: 20 Sec   Memory Limit: 256 MB
Submit: 506   Solved: 284
[ 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

Sample Output

661
388


超好推得公式


用前缀和搞搞,不过询问过多复杂度也不低

#include
#include
using namespace std;
int a[2005][2005], b[2005][2005], sa[2005][2005], sb[2005][2005];
int Read()
{
	int x = 0, f = 1;
	char ch;
	ch = getchar();
	while(ch<'0' || ch>'9')
	{
		if(ch=='-')  f = -1;
		ch = getchar();
	}
	while(ch>='0' && ch<='9')
		x = x*10+ch-'0', ch = getchar();
	return x*f;
}
int main(void)
{
	long long ans;
	int n, m, i, j, x1, x2, y1, y2;
	while(scanf("%d%d", &n, &m)!=EOF)
	{
		for(i=1;i<=n;i++)
		{
			for(j=1;j<=n;j++)
			{
				a[i][j] = Read();
				sa[i][j] = sa[i-1][j]+a[i][j];
			}
		}
		for(i=1;i<=n;i++)
		{
			for(j=1;j<=n;j++)
			{
				b[i][j] = Read();
				sb[i][j] = sb[i][j-1]+b[i][j];
			}
		}
		while(m--)
		{
			x1 = Read(), y1 = Read();
			x2 = Read(), y2 = Read();
			if(x1>x2)  swap(x1, x2);
			if(y1>y2)  swap(y1, y2);
			ans = 0;
			for(i=1;i<=n;i++)
				ans += (long long)(sa[x2][i]-sa[x1-1][i])*(sb[i][y2]-sb[i][y1-1]);
			printf("%lld\n", ans);
		}
	}
	return 0;
}


你可能感兴趣的:(#,推理,游戏与技巧)