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;
}

原文地址:https://www.cnblogs.com/KirinSB/p/11634347.html

时间: 2024-10-03 22:08:34

Gym102361A Angle Beats(直角三角形 计算几何)题解的相关文章

Angle Beats Gym - 102361A(计算几何)

Angle Beats \[ Time Limit: 4000 ms \quad Memory Limit: 1048576 kB \] 题意 给出 \(n\) 个初始点以及 \(q\) 次询问,每次询问给出一个询问点 \(Q\),求包括 \(Q\) 点的直角三角形有多少个.保证 \(n+q\) 个点都不重复. 思路 对于每次询问,当 \(Q\) 为直角点时,以 \(Q\) 为原点,对 \(n\) 个点做象限极角排序,然后用双指针 \(L\). \(R\) 维护直角三角形的个数. \(L\) 指

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

题目链接:https://codeforces.com/gym/102361/problem/A 题意:给定二维平面上的\(n\)个点,\(q\)次询问,每次加入一个点,询问平面上有几个包含该点的直角三角形. 分析:这是一篇鸽了很久的题解,主要原因就是现场赛的时候这题惨遭卡常,锅++.现在回过头来想这题,主要问题出在现场赛时误判了\(map\)的时间复杂度,把极角排序的正确想法成功叉掉,以及现场赛时候的共线计数使用了\(gcd\),使得整体复杂度上升.(但还是有大佬拿gcd思想过了,我太菜了)现

【2019CCPC秦皇岛:A】Angle Beats 分类讨论 (unordered_map 加 hash)

题意:n个给定点,q个询问点,每次询问给出一个坐标A,问从n中选定两个点B,C,有多少种方案使得ABC是个直角三角形. 思路:直角三角形能想的就那几个,枚举边,枚举顶点,这个题都行,写的枚举顶点的,A点分两种情况,1是直角,2是非直角.防止误差,用分数表示斜率,然后用了map<pair<int,int> int> 发现t了,改成unordered_map发现这个unordered_map只能映射一个,即unordered_map<ll, int>,所以得用到hash,把

UVa 1643 Angle and Squares (计算几何)

题意:有n个正方形和一个角(均在第一象限中),使这些正方形与这个角构成封闭的阴影区域,求阴影区域面积的最大值. 析:很容易知道只有所有的正方形的对角形在一条直线时,是最大的,然后根据数学关系,就容易得到答案. 代码如下: #pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #include <string> #include <cstdlib> #incl

codeforces gym 102268 300iq round

暂时只能写签到题,别的题解之后补 A.Angle Beats B.Best Subsequence 有点有趣的二分 显然二分之后就是找到一个长度恰好为k的合法环了 先证明一个引理,如果可以找到一个长度大于k的环一定可以找到一个长度等于k的环 固定头尾不动之后就可以使用归纳法证明一个长度大于3的环都可以删掉一个点 为啥呢?,因为考虑任意三个连续的点,除非中间的点是最小值,否则都可以删掉这个点 很容易证明长度大于3的序列至少存在一组三个连续的点满足中间的点可以删去吧 而长度恰好是3的时候吧中间的点删

2019 China Collegiate Programming Contest Qinhuangdao Onsite

目录 Contest Info Solutions A. Angle Beats D. Decimal F. Forest Program I. Invoker J. MUV LUV EXTRA Contest Info Practice Link Solved A B C D E F G H I J K L 5/12 O - - O - O - - - O ? - O 在比赛中通过 ? 赛后通过 ! 尝试了但是失败了 - 没有尝试 Solutions A. Angle Beats 题意: 给出

【日常训练】【ACM】2019-10-27_ccpc2019秦皇岛

A: Angle Beats 我们写掉了,但是不是我写的,是pcf写的.他卡了好久常数,所以我就不写题解了 D: Decimal 题面 每次给你一个正整数\(n\),问\(\frac{1}{n}\)在十进制下是否是无限小数. 题解 如果\(n\)只有2或者5作为质因子,那么就不是,否则就是. 这题很傻. E: Escape 这题有点意思. 网络流 题面 给你一个\(n\times m\)的网格,有些格子可能有障碍. 在第\(1\)行上面放了若干个机器人,第\(i\)个在\((0,p_i)\).

寒假代更新计划

[ ] \(10\)套\(CF\) \(div2\) [ ] 数论算法 [ ] 网络流 [ ] 数据结构 [ ] 计算几何 题解更新到\(30\)篇 原文地址:https://www.cnblogs.com/Hock/p/12238107.html

HDU 3532 Max Angle(计算几何——极角排序)

传送门 Max Angle Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 704    Accepted Submission(s): 253 Problem Description Given many points in a plane, two players are playing an interesting game. Pl