Gym102361A Angle Beats(直角三角形 计算几何)题解

Posted kirinsb

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Gym102361A Angle Beats(直角三角形 计算几何)题解相关的知识,希望对你有一定的参考价值。

题意:

\\(n\\)个点,\\(q\\)个询问,每次问包含询问点的直角三角形有几个

思路:

技术图片

代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn = 8000 + 10;
typedef long long ll;
const ll mod = 998244353;
typedef unsigned long long ull;
struct Point
    ll x, y;
    int flag;
be[maxn], p[maxn];
int Qua(Point a)
    if(a.x > 0 && a.y >= 0) return 1;
    if(a.x <= 0 && a.y > 0) return 2;
    if(a.x < 0 && a.y <= 0) return 3;
    if(a.x >= 0 && a.y < 0) return 4;

int cmp1(Point a, Point b) 
    ll d = a.x * b.y - b.x * a.y;
    if(d == 0) 
        return a.x < b.x;
    
    else
        return d > 0;
    

bool cmp(const Point &a, const Point &b)
    int qa = Qua(a), qb = Qua(b);
    if(qa == qb)
        return cmp1(a, b);
    
    return qa < qb;

int angle(Point a, Point b)    //爆ll
    ull now = (ull)(a.x - b.x) * (a.x - b.x) + (ull)(a.y - b.y) * (a.y - b.y);
    ull exc = a.x * a.x + a.y * a.y + b.x * b.x + b.y * b.y;
    if(now == exc) return 0;    //直角
    if(now < exc) return -1;    //锐角
    return 1;   //钝角

ll cross(Point a, Point b)
    return a.x * b.y - a.y * b.x;

ll ans[maxn];
int main()
    int n, q;
    scanf("%d%d", &n, &q);
    int cnt = 0;
    for(int i = 1; i <= n; i++)
        cnt++;
        scanf("%lld%lld", &be[cnt].x, &be[cnt].y);
        be[cnt].flag = 0;
        p[cnt] = be[cnt];
    
    for(int i = 1; i <= q; i++)
        cnt++;
        scanf("%lld%lld", &be[cnt].x, &be[cnt].y);
        be[cnt].flag = i;
        p[cnt] = be[cnt];
    

    for(int i = n + 1; i <= cnt; i++)
        p[0] = be[i];    //直角点
        int tot = 0;
        for(int j = 1; j <= n; j++)
            p[j].x = be[j].x - be[i].x;
            p[j].y = be[j].y - be[i].y;
            p[j].flag = be[j].flag;
        
        sort(p + 1, p + n + 1, cmp);
        for(int j = 1; j <= n; j++)
            p[j + n] = p[j];
        

        int R = 2;
        for(int L = 1; L <= n; L++)
            while(R <= 2 * n)
                if(cross(p[L], p[R]) < 0) break;
                if(angle(p[L], p[R]) >= 0) break;
                R++;
            
            int tR = R;
            while(tR <= 2 * n)
                if(cross(p[L], p[tR]) <= 0) break;
                if(angle(p[L], p[tR]) != 0) break;
                ans[be[i].flag]++;
                tR++;
            
        
    

    for(int i = 1; i <= n; i++)
        p[0] = be[i];   //非直角点
        int tot = 0;
        for(int j = 1; j <= cnt; j++)
            if(j == i) continue;
            tot++;
            p[tot].x = be[j].x - be[i].x;
            p[tot].y = be[j].y - be[i].y;
            p[tot].flag = be[j].flag;
        
        sort(p + 1, p + tot + 1, cmp);
        for(int j = 1; j <= tot; j++)
            p[j + tot] = p[j];
        

        int R = 2;
        for(int L = 1; L <= tot; L++)
            while(R <= 2 * tot)
                if(cross(p[L], p[R]) < 0) break;
                if(angle(p[L], p[R]) >= 0) break;
                R++;
            
            int tR = R;
            while(tR <= 2 * tot)
                if(cross(p[L], p[tR]) <= 0) break;
                if(angle(p[L], p[tR]) != 0) break;
                if(p[L].flag && p[tR].flag == 0)
                    ans[p[L].flag]++;
                
                else if(p[L].flag == 0 && p[tR].flag)
                    ans[p[tR].flag]++;
                
                tR++;
            
        
    

    for(int i = 1; i <= q; i++) printf("%lld\\n", ans[i]);

    return 0;

以上是关于Gym102361A Angle Beats(直角三角形 计算几何)题解的主要内容,如果未能解决你的问题,请参考以下文章

Codeforces Gym 102361A Angle Beats CCPC2019秦皇岛A题 题解

CCPC秦皇岛gym102361A. Angle Beats

CCPC秦皇岛gym102361A. Angle Beats

CCPC秦皇岛gym102361A. Angle Beats

GYM102268 Angle Beats(一般图匹配)

秦皇岛站2019CCPC A.Angel Beats