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

Angle Beats

\[ Time Limit: 4000 ms \quad Memory Limit: 1048576 kB \]

题意

给出 \(n\) 个初始点以及 \(q\) 次询问,每次询问给出一个询问点 \(Q\),求包括 \(Q\) 点的直角三角形有多少个。保证 \(n+q\) 个点都不重复。

思路

  1. 对于每次询问,当 \(Q\) 为直角点时,以 \(Q\) 为原点,对 \(n\) 个点做象限极角排序,然后用双指针 \(L\)\(R\) 维护直角三角形的个数。 \(L\) 指针用来枚举其中的一条直角边, \(R\) 指针用来寻找在另一条直角边上的点有多少个,每次找 \(QL\) 这条边逆时针方向的另一条边\(QR\)。所以当 \(L\) 往逆时针转动时,\(R\) 也会往逆时针转动,那么就可以用双指针直接维护出来了,特别注意一下多个点在同一条直线上的情况就可以了。
  2. \(Q\) 不是直角点时,可以离线处理,把 \(n+q\) 个点全部存出来,然后枚举以 \(n\) 个初始点为直角点时,对哪些的 \(Q\) 点有贡献,维护方法同上。

最后的复杂度为 \(O\left(qnC_1 + n(n+q)C_2\right)\)\(C_1、C_2\) 取决于在枚举直角点为原点后,到原点在同一条直线上的点数量。
我试过把 \(n+q\) 个节点全部提取出来,然后暴力枚举每个点为直角点的情况,但是这样复杂度会 \(T\)

#include
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 1e4+10;

struct Point {
    ll x, y;
    int id;
} p[maxn], be[maxn];
int n, m;
int ans[maxn];

int cmp1(Point a, Point b) {
    ll d = a.x*b.y - b.x*a.y;
    if(d == 0) {
        return a.x0;
    }
}
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 cmp(Point a, Point b) {
    if(Qua(a) == Qua(b))    return cmp1(a, b);
    else    return Qua(a)

转载于:https://www.cnblogs.com/Jiaaaaaaaqi/p/11631203.html

你可能感兴趣的:(Angle Beats Gym - 102361A(计算几何))