Angle Beats(计算几何)
思路: 排序+暴力枚举。
分两种情况: 作为直角顶点. 不作为直角顶点。
此题最重要的是利用 将向量去重,如
时间复杂度:
#include<bits/stdc++.h>
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<int,int>
#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;
}