題目連接
題意
- 就是給你個整數點,個詢問,每次詢問給你一個點,求個點中有多少點對,使得三點構成直角三角形,保證所有個點兩兩互不相同
題解
-
兩種解法:第一種哈希,第二種二分
-
分兩種情況討論一下
- 點作爲直角
- 點作爲直角三角形當中的一個銳角
首先需要預處理出所有個點兩兩之間的斜率,要麼把用分數表示斜率的分子和分母,成一個數,要麼用一個表示分數的結構體表示即可,然後對於第一種情況,每次詢問先預處理出與所有個點之間的斜率,然後用或者二分(重載一下結構體即可)去查詢與他垂直的點數量,這樣一個直角三角形被統計了兩次,答案除以,對於第二種類似處理即可,注意哈希方法過不了,卡了內存,現場賽是給了兩個的
複雜度
- 二分
- 哈希
代碼一(哈希)
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e3+10;
struct point{
int x,y;
point(int a=0,int b=0) {x=a;y=b;}
point operator-(point other) {return point(x-other.x,y-other.y);}
}a[maxn];
int gcd(int a,int b) {return b==0?a:gcd(b,a%b);}
unordered_map<unsigned long long,int>o[maxn],b;
unsigned int Hash(point p) {
int GCD=gcd(abs(p.x),abs(p.y));
p.x/=GCD,p.y/=GCD;
if(p.x<0) {p.x=-p.x;p.y=-p.y;}
if(p.x==0) p.y=1;
return (unsigned int)p.x*233334*233334+(unsigned int)p.y*233333;
}
int n,q,x,y;
unsigned int k[maxn];
int main() {
while(~scanf("%d %d",&n,&q)) {
for(int i=1;i<=n;i++) scanf("%d %d",&a[i].x,&a[i].y);
for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(j!=i) o[i][Hash(a[j]-a[i])]++;
while(q--) {
long long ans=0;
scanf("%d %d",&x,&y);
for(int i=1;i<=n;i++) k[i]=Hash(point(a[i].y-y,-(a[i].x-x)));
for(int i=1;i<=n;i++) b[Hash(a[i]-point(x,y))]++;
for(int i=1;i<=n;i++) ans+=b[k[i]];
ans/=2;
for(int i=1;i<=n;i++) ans+=o[i][k[i]];
printf("%lld\n",ans);
b.clear();
}
for(int i=1;i<=n;i++) o[i].clear();
}
}
代碼二(二分)
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e3+10;
struct point{
int x,y;
point(int a=0,int b=0) {x=a;y=b;}
point operator-(point other) {return point(x-other.x,y-other.y);}
friend bool operator<(const point &a,const point &b) {
return 1LL*a.y*b.x<1LL*a.x*b.y;
}
friend void init(point &p) {
if(p.x<0) {p.x=-p.x,p.y=-p.y;}
if(p.x==0) p.y=1;
}
}a[maxn],b[maxn],o[maxn][maxn];
int n,x,y,q;
int main() {
while(~scanf("%d %d",&n,&q)) {
for(int i=1;i<=n;i++) scanf("%d %d",&a[i].x,&a[i].y);
for(int i=1;i<=n;i++) {
int qwq=0;
for(int j=1;j<=n;j++) if(j!=i) o[i][++qwq]=(a[j]-a[i]),init(o[i][qwq]);
}
for(int i=1;i<=n;i++) sort(o[i]+1,o[i]+n);
while(q--) {
scanf("%d %d",&x,&y);
for(int i=1;i<=n;i++) b[i]=a[i]-point(x,y),init(b[i]);
sort(b+1,b+n+1);long long ans=0;
for(int i=1;i<=n;i++) {
point chuizhi=point(b[i].y,-b[i].x);init(chuizhi);
ans+=upper_bound(b+1,b+n+1,chuizhi)-lower_bound(b+1,b+n+1,chuizhi);
}
ans/=2;
for(int i=1;i<=n;i++) {
point chuizhi=point(y-a[i].y,-(x-a[i].x));init(chuizhi);
ans+=upper_bound(o[i]+1,o[i]+n,chuizhi)-lower_bound(o[i]+1,o[i]+n,chuizhi);
}
printf("%lld\n",ans);
}
}
}