Angle Beats(計算幾何)

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個點pip_i,然後q次詢問,在每次詢問時,給出一個座標aia_i,求每個aia_i在p中任選兩個點能組成多少直角三角

題解

先想到斜率,然後又從計算幾何板子繞回斜率來了。斜率很噁心,我是用pair存的,斜率九成九爆double??我猜的。。。
因爲aia_i是否是直角點會影響我們討論的邊,所以我們分爲兩種情況分別爲aia_i是直角點和不是直角點

1.aia_i是直角點。此時情況即爲
在這裏插入圖片描述

在這種情況下我們預處理出每個pjp_jaia_i的斜率,用map存下來每個斜率的點的數量
然後枚舉pjp_j,顯然我們可以將pjp_j旋轉到九十度到圖中pkp_k的位置,即直線b上的所有點pp都滿足條件
需要注意的是最後會出現重複加的情況,除2即可。
2.aia_i不是直角點。
在這裏插入圖片描述
在這種情況下,選擇離線處理,然後再對每一個pjp_j預處理出其他點的斜率。
然後枚舉aia_i,依舊是圖中直線b上的所有點p都滿足,也就是map[b]map[b的斜率]

斜率用分數表示,應該沒有人不知道分數用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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章