ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【题解】[USACO20FEB]Equilateral Triangles P

2021-06-09 23:03:58  阅读:177  来源: 互联网

标签:Equilateral int 题解 rep 坐标轴 ans mathcal 复杂度 Triangles


基础数数题。

曼哈顿距离不方便数点,比较套路的转化为切比雪夫距离。

那么现在要数三元组 \((i,j,k)\) 个数使得两两距离相等。

首选一下发现只用两种情况,第一种是三个点构成等腰直角三角形,第二种是三个点构成锐角三角形使得存在一条平行于坐标轴的边,且该边上的高和它的长度相等。

充分性也不难证明,首先如果三条边都不与坐标轴平行,那么反证一下发现不存在这种情况。

否则一定存在一条边与坐标轴平行,画出来如果这条边上的高与它不相等,那么也不满足条件。

最后钝角三角形显然不满足条件。所以只剩下上面两种情况。

具体实现,我们记录行前缀和,和列前缀和,然后枚举与坐标轴平行的边。求前缀和的时间复杂度是 \(\mathcal{O}(N^2)\) ,枚举边的时间复杂度是 \(\mathcal{O}(N^3)\) ,查询是 \(\mathcal{O}(1)\) 的,所以总时间复杂度为 \(\mathcal{O}(N^3)\) 。

注意实现细节,比如转化为切比雪夫距离后坐标可能为负数需要处理一下,坐标值域会扩大为原来的两倍。如果直接枚举新的值域会有 \(8\) 倍常数直接爆炸。但是转化之后的网格会变稀疏,轻微剪枝就拿到了最优解(doge

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define pre(i,a,b) for(int i=a;i>=b;i--)
#define N 1005
using namespace std;
int n,a[N][N],u[N][N],v[N][N];char s[N][N];
int main(){
	scanf("%d",&n);
	rep(i,1,n)scanf("%s",s[i]+1);
	rep(i,1,n)rep(j,1,n)if(s[i][j]=='*')a[i+j][i-j+n]=1;
	int m=2*n;
	rep(i,1,m)rep(j,1,m)u[i][j]=u[i][j-1]+a[i][j];
	rep(j,1,m)rep(i,1,m)v[i][j]=v[i-1][j]+a[i][j];
	int ans=0;
	rep(k,1,m)rep(i,1,m)if(a[i][k])rep(j,i+1,m)if(a[j][k]){
		if(k>j-i)ans+=v[j][k-j+i]-v[i-1][k-j+i];
		if(m-k>=j-i)ans+=v[j][k+j-i]-v[i-1][k+j-i];
	}
	rep(k,1,m)rep(i,1,m)if(a[k][i])rep(j,i+2,m)if(a[k][j]){
		if(k>j-i)ans+=u[k-j+i][j-1]-u[k-j+i][i];
		if(m-k>=j-i)ans+=u[k+j-i][j-1]-u[k+j-i][i];
	}
	printf("%d\n",ans);
	return 0;
}

标签:Equilateral,int,题解,rep,坐标轴,ans,mathcal,复杂度,Triangles
来源: https://www.cnblogs.com/SharpnessV/p/14869257.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有