[USACO3.3.4]range

  题目传送门:http://www.nocow.cn/index.php/Translate:USACO/range

  这道题的话如果不是之前做过类似的题目,我想我是做不出来的,大概就是先预处理s[i][j],表示前i行前j列有多少个1,然后O(1)时间判断这个正方形是否有1。

  s[i][j]显然等于是s[i-1][j]+s[i][j-1]-s[i-1][j-1]+f[i][j](两个多边形重复的部分为s[i-1][j-1])

  而判断第i行到第l行,第j列到第k列这个多边形内有没有(j-k+1)*(l-i+1)个1,显然只需判断s[i][j]-s[i-1][k]-s[l][j-1]+s[i-1][j-1]是否等于(j-k+1)*(l-i+1)就行了。(两个多边形的重复部分为s[i-1][j-1])

  会有一点乱,但只要想一想图就好了,而且这道题是正方形,只要枚举边的长度就好了.

  

/*
ID:abc31261
LANG:C++
TASK:range
*/

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int maxn=260;
int n,f[maxn][maxn],s[maxn][maxn],num[maxn];
int main()
{
	int i,j,l;
	freopen("range.in","r",stdin);
	freopen("range.out","w",stdout);
	scanf("%d",&n);
	for (i=1;i<=n;i++)
		for (j=1;j<=n;j++)scanf("%01d",&f[i][j]);
	memset(s,0,sizeof(s));
	memset(num,0,sizeof(num));
	for (i=1;i<=n;i++)
		for (j=1;j<=n;j++)s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]+f[i][j];
	for (i=1;i<=n;i++)
		for (j=1;j<=n;j++)
			for (l=2;l<=min(n-i+1,n-j+1);l++)
			{
				int x=i+l-1,y=j+l-1;
				if (s[x][y]-s[x][j-1]-s[i-1][y]+s[i-1][j-1]==l*l)num[l]++;
			}
	for (i=1;i<=n;i++)
		if (num[i]!=0)printf("%d %d\n",i,num[i]);
	return 0;
}

  

 

posted @ 2016-03-17 23:13  Sun_Sea  阅读(142)  评论(0编辑  收藏  举报