列表

详情


NC54664. 捡金币

描述

Tyl 准备了一个尺寸为 n*m(一共 n 行,每行 m 个格子)的棋盘,并在棋盘的每个格子里都放入了一些金币。 用 (x, y) 表示位于第 x  行第 y 列的格子,两个格子 (a, b) 和 (c, d) 的距离定义为 abs(a-c)+abs(b-d) 现在 Tyl 准备问你 q 个问题,对于每一个问题,给定 x,y,k ,请你求出离 (x, y) 距离不超过 k 的所有格子里的金币总和是多少。

输入描述

第一行是一个整数  T(1<=T<=100),表示数据组数。
对于每一组数据:
第一行是 2 个整数 n,m(1<=n,m<=1000) ,表示棋盘的尺寸。
接下来一共 n 行,每行 m 个整数,用以表示棋盘内每个格子放入的金币数量,每个格子内放入的金币数量 v 满足 (1<=v<=1000000)。
接下来 1 个整数 q(1<=q<=100000) 表示询问个数。
接下来一共 q 行,每行 3 个整数 x,y,k(1<=x<=n, 1<=y<=m, 1<=k<=max(n,m)) 表示一组询问。

输出描述

对于每一个询问 x,y,k  ,输出一行包括一个数字表示离 (x,y) 距离不超过 k 的所有格子里的金币总和是多少。

示例1

输入:

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

输出:

6
30
62
78 

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 355ms, 内存消耗: 48872K, 提交时间: 2019-11-17 17:59:45

#include<cstdio>
#include<cstring>
using namespace std;
int t,i,j,x,y,x1,y1,k,n,m,q,n1,m1;
int a[2000][2000];
long long b[2000][2000];
inline int max(int a,int b)
{
	return a>b?a:b;
}
inline int min(int a,int b)
{
	return a<b?a:b;
}
int main()
{
	scanf("%d",&t);
	for (;t;--t)
	{
		scanf("%d%d",&n,&m);
		memset(a,0,sizeof(a));
		for (i=1;i<=n;++i)
			for (j=1;j<=m;++j) scanf("%d",&a[i-j+m][i+j-1]);
		n1=n+m-1;
		m1=n+m-1;
		for (i=1;i<=n1;++i)
			for (j=1;j<=m1;++j) b[i][j]=a[i][j]+b[i-1][j]+b[i][j-1]-b[i-1][j-1];
		scanf("%d",&q);
		for (;q;--q)
		{
			scanf("%d%d%d",&x,&y,&k);
			x1=x-y+m;
			y1=x+y-1;
			printf("%lld\n",b[min(x1+k,n1)][min(y1+k,m1)]-b[max(x1-k-1,0)][min(y1+k,m1)]-b[min(x1+k,n1)][max(y1-k-1,0)]+b[max(x1-k-1,0)][max(y1-k-1,0)]);
		}
	}
}

C++11(clang++ 3.9) 解法, 执行用时: 1390ms, 内存消耗: 9820K, 提交时间: 2019-11-17 16:16:15

# include <iostream>
# include <cstdio>

using namespace std;

long long A[1010][1010];

int main(void)
{
	//freopen("aaa.in","r",stdin);
	int T;
	scanf("%d",&T);
	while(T--)
	{
		int n,m;
		scanf("%d%d",&n,&m);	
		for (int i=1;i<=n;i++)
		for (int j=1,a;j<=m;j++)
		{
			scanf("%d",&a);
			A[i][j] = A[i][j-1]+a;
		}
		int q,x,y,k;
		scanf("%d",&q);
		while(q--)
		{
			scanf("%d%d%d",&x,&y,&k);
			long long ans=0;
			int r=min(y+k,m),l=max(1,y-k),up,low;
			ans+=A[x][r]-A[x][l-1];
			for (int i=k-1;i>=0;i--)
			{
				r = min(y+i,m);l = max(1,y-i);
				up = x-(k-i);
				if (up>=1) ans+=A[up][r]-A[up][l-1];
				low = x+(k-i);
				if (low<=n) ans+=A[low][r]-A[low][l-1];
			}
			printf("%lld\n",ans);
		}
	}
	return 0;
}

上一题