[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;
}

浙公网安备 33010602011771号