atcoder tenka1 2018 e Equilateral - 前缀和

题目大意:给一张黑白网格图,问有多少黑点的无序三元组,两两曼哈顿距离相等。300。
题解:转切比雪夫距离,发现一定有至少两个点的连向平行于坐标轴。
枚举计算即可,注意等腰直角三角形的情况若不处理会被计两次。

#include<bits/stdc++.h>
#define gc getchar()
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define Rep(i,v) rep(i,0,(int)v.size()-1)
#define lint long long
#define db long double
#define pb push_back
#define mp make_pair
#define fir first
#define sec second
#define debug(x) cerr<<#x<<"="<<x
#define sp <<" "
#define ln <<endl
using namespace std;
typedef pair<int,int> pii;
typedef set<int>::iterator sit;
inline int inn()
{
	int x,ch;while((ch=gc)<'0'||ch>'9');
	x=ch^'0';while((ch=gc)>='0'&&ch<='9')
		x=(x<<1)+(x<<3)+(ch^'0');return x;
}
#define Ss(x,y) (x>=1&&x<=n&&y>=1&&y<=m&&v[x][y])
const int N=1010;int v[N][N],s[N][N];char str[N][N];
inline int S(int a,int b,int c,int d)
{
	return s[c][d]-s[a-1][d]-s[c][b-1]+s[a-1][b-1];
}
int main()
{
	int n=inn(),m=inn(),ans=0;
	rep(i,1,n) scanf("%s",str[i]+1);
	rep(i,1,n) rep(j,1,m)
		v[i+j][i-j+m]=(str[i][j]=='#');
	int nn=n+m,mm=n-1+m;n=nn,m=mm;
	rep(i,1,n) rep(j,1,m) s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]+v[i][j];
	rep(i,1,n) rep(j,1,m) rep(k,j+2,m)
	{
		int d=k-j;if(!v[i][j]||!v[i][k]) continue;
		if(i-d>=1) ans+=S(i-d,j+1,i-d,k-1);
		if(i+d<=n) ans+=S(i+d,j+1,i+d,k-1);
	}
	rep(i,1,m) rep(j,1,n) rep(k,j+2,n)
	{
		int d=k-j;if(!v[j][i]||!v[k][i]) continue;
		if(i-d>=1) ans+=S(j+1,i-d,k-1,i-d);
		if(i+d<=m) ans+=S(j+1,i+d,k-1,i+d);
	}
	rep(i,1,n) rep(j,1,m)
	{
		if(!v[i][j]) continue;
		rep(d,1,max(n,m))
		{
			if(Ss(i-d,j)&&Ss(i,j-d)) ans++;
			if(Ss(i-d,j)&&Ss(i,j+d)) ans++;
			if(Ss(i+d,j)&&Ss(i,j-d)) ans++;
			if(Ss(i+d,j)&&Ss(i,j+d)) ans++;
		}
	}
	return !printf("%d\n",ans);
}

猜你喜欢

转载自blog.csdn.net/Mys_C_K/article/details/83475663