「CodePlus 2017 12 月赛」可做题1-题解

本文介绍了一种高效判断矩阵是否为巧妙矩阵的算法,通过预处理2x2子矩阵并利用二维前缀和,实现O(nm+T)的时间复杂度,适用于1≤n,m≤500的大规模矩阵判断。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目地址

这个题虽然简单,但是还是有一个非常不错的小技巧,所以还是记录一下。


  • 题意简述

给你一个 n × m n\times m n×m的矩阵,我们定义一个矩阵是巧妙的,满足以下条件:

任意从其中选择 n n n 个不同行不同列的位置,其上的权值之和均相等。

例如: ∣ 1   2   3 4   5   6 7   8   9 ∣ \begin{vmatrix}1\ 2\ 3\\ 4\ 5\ 6\\ 7\ 8\ 9\end{vmatrix} 1 2 34 5 67 8 9是巧妙的,因为满足:
1 + 5 + 9 = 1 + 6 + 8 = 2 + 4 + 9 = 2 + 6 + 7 = 3 + 5 + 7 = 3 + 4 + 8 = 15 1+5+9=1+6+8=2+4+9=2+6+7=3+5+7=3+4+8=15 1+5+9=1+6+8=2+4+9=2+6+7=3+5+7=3+4+8=15

而矩阵 ∣ 1   2 2   1 ∣ \begin{vmatrix}1\ 2\\ 2\ 1\end{vmatrix} 1 22 1不是巧妙的,因为 1 + 1 ̸ = 2 + 2 1+1\not=2+2 1+1̸=2+2

每次询问你给出矩阵中的一个子矩阵是否是巧妙的。

1 ≤ n , m ≤ 500 , T ≤ 1 0 5 , v a l ≤ 1 0 9 1\leq n,m\leq 500,T\leq 10^5,val\leq10^9 1n,m500,T105,val109


其实不难发现,对于一个矩阵中的 2 × 2 2\times 2 2×2的一个子矩阵,例如 ∣ a   b c   d ∣ \begin{vmatrix}a\ b\\ c\ d\end{vmatrix} a bc d,如果 a + d ̸ = c + d a+d\not=c+d a+d̸=c+d,那么对于整个矩阵,必定会有一种选法为 a + d + { e l s e } , c + d + { e l s e } a+d+\{else\},c+d+\{else\} a+d+{else},c+d+{else},那么这个肯定不相等,所以这个矩阵肯定不巧妙。

所以我们预处理以每个 ( i , j ) (i,j) (i,j)为右下角的 2 × 2 2\times 2 2×2的矩阵是否巧妙,是的话 v [ i ] [ j ] = 0 v[i][j]=0 v[i][j]=0,否则 v [ i ] [ j ] = 1 v[i][j]=1 v[i][j]=1,然后维护一个 v v v的二维前缀和,每次询问一个矩阵,就是看这个矩阵里面是否有 v [ i ] [ j ] ̸ = 0 v[i][j]\not=0 v[i][j]̸=0,所以就可以 O ( n m + T ) O(nm+T) O(nm+T)的完成这个题了。

#include<cstdio>
using namespace std;
const int N=510;
char c;
void read(int &x){
	x=0;c=getchar();
	while(c<'0'||c>'9')c=getchar();
	while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c&15),c=getchar();
}
int mp[N][N],isok[N][N],n,m,T,x,y,K,now;
int main(){
	read(n);read(m);read(T);
	for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)read(mp[i][j]);
	for(int i=2;i<=n;++i){
		for(int j=2;j<=m;++j){
			isok[i][j]=((mp[i][j]+mp[i-1][j-1])!=(mp[i-1][j]+mp[i][j-1]))
			+(isok[i-1][j]+isok[i][j-1]-isok[i-1][j-1]);
		}
	}
	while(T--){
		read(x);read(y);read(K);
		++x;++y;K-=2;
		if(~K){
			now=isok[x+K][y+K]-isok[x-1][y+K]-isok[x+K][y-1]+isok[x-1][y-1];
			if(!now)puts("Y");
			else puts("N");
		}else puts("Y");
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

VictoryCzt

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值