Angle Beats(计算几何)

Angle Beats(计算几何)

思路: m a p map map排序+暴力枚举。

分两种情况: 1. Q [ i ] 1.Q[i] 1.Q[i]作为直角顶点. 2. Q [ i ] 2.Q[i] 2.Q[i]不作为直角顶点。

此题最重要的是利用 m a p map map将向量去重,如 ( 2 , 1 ) = ( 4 , 2 ) (2,1)=(4,2) (2,1)=(4,2)

时间复杂度: O ( n q + l o g ( n + q ) ) O(nq+log(n+q)) O(nq+log(n+q))

#include
using namespace std;
typedef long long ll;
const int N=2e3+5,M=2e4+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a,b) memset(a,b,sizeof a)
#define lx x<<1
#define rx x<<1|1
#define reg register
#define PII pair
#define fi first
#define se second
#define pb push_back
#define il inline
struct point{
	ll x,y;
	il point fun()const{	//保证x>=0 在第1,4象限,便于排序 
		if(x<0||(!x&&y<0)) return {-x,-y};
		return *this;
	}
	bool operator <(const point&p) const{	//用map实现分类.(2,1)=(4,2)是同一个向量. 
		point a=fun(),b=p.fun();	//tan从大到小排序. 
		return a.x*b.y<b.x*a.y;
	}
	point operator-(const point&p)const{	//两点构成的向量 
		return {x-p.x,y-p.y};
	}
}a[N],Q[N],tmp;
map<point,int>mp;
int n,q,ans[N];
int main(){
	scanf("%d%d",&n,&q);
	for(int i=1;i<=n;i++) scanf("%lld%lld",&a[i].x,&a[i].y);
	for(int i=1;i<=q;i++) scanf("%lld%lld",&Q[i].x,&Q[i].y);
	for(int i=1;i<=q;i++){	//Q[i]作为直角顶点. 
		mp.clear();
		for(int j=1;j<=n;j++)
			mp[a[j]-Q[i]]++;
		for(int j=1;j<=n;j++){
			tmp=a[j]-Q[i];
			tmp={-tmp.y,tmp.x};
			ans[i]+=mp[tmp];
		}
		ans[i]>>=1;//直角的两条边都被算了,所以要除以2. 
	}
	for(int i=1;i<=n;i++){	//a[i]作为直角顶点. 
		mp.clear();
		for(int j=1;j<=n;j++)
			if(i!=j) mp[a[j]-a[i]]++;
		for(int j=1;j<=q;j++){
			tmp=Q[j]-a[i];
			tmp={-tmp.y,tmp.x};
			ans[j]+=mp[tmp];
		}
	}
	for(int i=1;i<=q;i++) printf("%d\n",ans[i]);
	return 0;
}

你可能感兴趣的:(计算几何)