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

题目地址

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


  • 题意简述

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

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

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

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

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

1n,m500,T105,val1091\leq n,m\leq 500,T\leq 10^5,val\leq10^9


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

所以我们预处理以每个(i,j)(i,j)为右下角的2×22\times 2的矩阵是否巧妙,是的话v[i][j]=0v[i][j]=0,否则v[i][j]=1v[i][j]=1,然后维护一个vv的二维前缀和,每次询问一个矩阵,就是看这个矩阵里面是否有v[i][j]̸=0v[i][j]\not=0,所以就可以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;
}
posted @ 2018-11-03 09:50  VictoryCzt  阅读(202)  评论(0编辑  收藏  举报