Angle Beats
Time Limit: 20000/15000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 1435 Accepted Submission(s): 274
Problem Description
Given n points P1, P2, … , Pn on 2D plane and q queries. In i-th query, a point Ai is given, and you should determine the number of tuples (u, v) that 1 ≤ u < v ≤ n and Ai , Pu, Pv form a non-degenerate right-angled triangle.
Input
The first line contains two positive integers n, q (2 ≤ n ≤ 2 000, 1 ≤ q ≤ 2 000), denoting the numberof given points and the number of queries.
Next n lines each contains two integers xi , yi (|xi|, |yi| ≤ 109), denoting a given point Pi.
Next q lines each contains two integers xi , yi (|xi|, |yi| ≤ 109), denoting a query point Ai.
It is guaranteed that the input n + q points are all pairwise distinct.
Output
Output q lines each contains a non-negative integer, denoting the answer to corresponding query.
Sample Input
4 2
0 1
1 0
0 -1
-1 0
0 0
1 1
Sample Output
4
3
Hint
For query (0, 0), the 4 right-angled triangles are
� {(0, 0),(0, 1),(1, 0)}
� {(0, 0),(0, 1),(-1, 0)}
� {(0, 0),(0,-1),(1, 0)}
� {(0, 0),(0,-1),(-1, 0)}
For query (1, 1), the 3 right-angled triangles are
� {(1, 1),(0, 1),(1, 0)}
� {(1, 1),(0, 1),(0,-1)}
� {(1, 1),(1, 0),(-1, 0)}
題意
先給出平面上的n個點,然後q次詢問,在每次詢問時,給出一個座標,求每個在p中任選兩個點能組成多少直角三角
題解
先想到斜率,然後又從計算幾何板子繞回斜率來了。斜率很噁心,我是用pair存的,斜率九成九爆double??我猜的。。。
因爲是否是直角點會影響我們討論的邊,所以我們分爲兩種情況分別爲是直角點和不是直角點
1.是直角點。此時情況即爲
在這種情況下我們預處理出每個對的斜率,用map存下來每個斜率的點的數量
然後枚舉,顯然我們可以將旋轉到九十度到圖中的位置,即直線b上的所有點都滿足條件
需要注意的是最後會出現重複加的情況,除2即可。
2.不是直角點。
在這種情況下,選擇離線處理,然後再對每一個預處理出其他點的斜率。
然後枚舉,依舊是圖中直線b上的所有點p都滿足,也就是
斜率用分數表示,應該沒有人不知道分數用pair存,然後取最簡分數,特殊的兩個用0/1,1/0吧。
代碼
// #include <bits/stdc++.h>
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <queue>
#include <cmath>
#include <string>
#include <cstring>
#include <map>
#include <unordered_map>
#include <set>
#include <vector>
#include <assert.h>
#include <cmath>
#include <ctime>
using namespace std;
#define me(x,y) memset((x),(y),sizeof (x))
#define MIN(x,y) ((x) < (y) ? (x) : (y))
#define MAX(x,y) ((x) > (y) ? (x) : (y))
#define SGN(x) ((x)>0?1:((x)<0?-1:0))
#define ABS(x) ((x)>0?(x):-(x))
// #define int __int128_t
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
const int maxn = 2200;
const int inf = __INT32_MAX__;
const ll INF = __LONG_LONG_MAX__;
const ll MOD = 998244353;
const double eps = 1e-8;
const double pi = std::acos(-1);
const string cars[] = {"?","?","?"};
struct Point{
int x,y;
Point(){}
Point(double _x,double _y){x = _x,y = _y;}
bool operator != (Point b)const{return x != b.x || y != b.y;}
bool operator < (Point b)const{return x == b.x ? y < b.y : x < b.x;}
};
Point p[maxn],a[maxn];
Point po[maxn<<1];
int num[maxn];
map<Point,int> mp;
map<pii,int> e;
pii pa(Point x,Point y){
pii pa;
pa.first = x.y - y.y;
pa.second = x.x - y.x;
if(pa.first == 0) pa.second = 1;
else if(pa.second == 0) pa.first = 1;
else{
int g = __gcd(pa.first,pa.second);
pa.first /= g,pa.second /= g;
if(pa.second < 0) pa.first = -pa.first,pa.second = -pa.second;
}
return pa;
}
pii rev(pii x){
swap(x.first,x.second);
x.first = -x.first;
if(x.second < 0) x.first = -x.first,x.second = -x.second;
if(x.second == 0) x.first = 1;
return x;
}
int main(){
ios::sync_with_stdio(false);
#ifndef ONLINE_JUDGE
freopen("1in.in","r",stdin);
freopen("1out.out","w",stdout);
#endif
int n,q;
while(cin>>n>>q){
me(num,0);
int tot=0;
for(int i = 1; i <= n; ++i) cin>>p[i].x>>p[i].y;
for(int i = 1; i <= q; ++i) cin>>a[i].x>>a[i].y;
for(int i = 1; i <= q; ++i){
e.clear();
for(int j = 1; j <= n; ++j) e[pa(p[j],a[i])]++;
for(int j = 1; j <= n; ++j){
pii tmp = pa(a[i],p[j]);
tmp = rev(tmp);
if(e.count(tmp)) num[i] += e[tmp];
}
num[i] /= 2;
}
for(int i = 1; i <= n; ++i){
e.clear();
for(int j = 1; j <= n; ++j){
if(i != j) e[pa(p[i],p[j])]++;
}
for(int j = 1; j <= q; ++j){
pii tmp = pa(a[j],p[i]);
tmp = rev(tmp);
if(e.count(tmp)) num[j] += e[tmp];
}
}
for(int i = 1; i <= q; ++i) cout<<num[i]<<endl;
}
return 0;
}