ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

牛客练习赛60 F、几何带师 (二维偏序 + 几何基础 + 思维)

2020-04-03 19:54:21  阅读:345  来源: 互联网

标签:偏序 练习赛 return Point LL get pos Ang 几何


题目:传送门

题意

 

 

 思路

官方题解

 

 

#include <bits/stdc++.h>
#define LL long long
#define ULL unsigned long long
#define mem(i, j) memset(i, j, sizeof(i))
#define rep(i, j, k) for(int i = j; i <= k; i++)
#define dep(i, j, k) for(int i = k; i >= j; i--)
#define pb push_back
#define make make_pair
#define INF INT_MAX
#define inf LLONG_MAX
#define PI acos(-1)
#define fir first
#define sec second
#define lb(x) ((x) & (-(x)))
using namespace std;

const int N = 1e6 + 5;

struct Point {
    LL x, y;
    Point(LL x = 0, LL y = 0) : x(x), y(y) { }
    Point operator + (const Point& A) const {
        return Point(x + A.x, y + A.y);
    }
    Point operator - (const Point& A) const {
        return Point(x - A.x, y - A.y);
    }
    bool operator < (const Point& A) const {
        return x < A.x || (x == A.x && y < A.y);
    }
    bool operator == (const Point& A) const {
        return x == A.x && y == A.y;
    }
};

LL Dot(Point A, Point B) {
    return A.x * B.x + A.y * B.y;
}
LL Cross(Point A, Point B) {
    return A.x * B.y - A.y * B.x;
}

double get_dis(Point A, Point B) {
    return sqrt(Dot(A - B, A - B));
}

struct note {
    LL x, y, add;
    note(LL x = 0, LL y = 0, LL add = 0) : x(x), y(y), add(add) { }
    bool operator < (const note& A) const {
        return x == A.x ? y < A.y : x < A.x;
    }
}E[N];

Point a[N];
int c[N << 1], n;
double Ang[N][2], pos[N << 1];
pair < int ,int > id[N];
LL res;

void add(int x, int val) {
    for(int i = x; i <= 200000; i += lb(i)) c[i] += val;
}
int sum(int x) {
    int ans = 0;
    for(int i = x; i > 0; i -= lb(i)) ans += c[i];
    return ans;
}

double get_Ang(double a, double b, double c) { /// 余弦定理算角度
    return acos((b * b + c * c - a * a) / (2 * b * c));
}

LL solve1(Point A, Point B) { /// 两点在线段AB同边的情况
    mem(c, 0);
    int tot = 0, cnt = 0;
    LL ans = 0;

    rep(i, 1, n) {
        if(Cross(B - A, a[i] - A) > 0) { /// 点 A[i] 在向量AB的左边
            tot++;
            Point P = a[i];
            double dispa = get_dis(P, A);
            double dispb = get_dis(P, B);
            double disab = get_dis(A, B);
            Ang[tot][0] = get_Ang(dispb, dispa, disab);
            Ang[tot][1] = PI - get_Ang(dispa, dispb, disab);
            pos[++cnt] = Ang[tot][0];
            pos[++cnt] = Ang[tot][1];
        }
    }

    sort(pos + 1, pos + 1 + cnt);

    rep(i, 1, tot) {
        id[i].fir = lower_bound(pos + 1, pos + 1 + cnt, Ang[i][0]) - pos;
        id[i].sec = lower_bound(pos + 1, pos + 1 + cnt, Ang[i][1]) - pos;
    }

    sort(id + 1, id + 1 + tot);

    rep(i, 1, tot) {
        ans += sum(200000) - sum(id[i].sec);
        add(id[i].sec, 1);
    }
    return ans;
}

LL solve2(Point A, Point B) {/// 两点在AB的异侧
    mem(c, 0);
    int cnt = 0;
    LL ans = 0;

    rep(i, 1, n) {
        Point P = a[i];
        double dispa = get_dis(P, A);
        double dispb = get_dis(P, B);
        double disab = get_dis(A, B);
        Ang[i][0] = get_Ang(dispb, dispa, disab);
        Ang[i][1] = get_Ang(dispa, dispb, disab);
        if(Cross(B - A, a[i] - A) > 0) {
            Ang[i][0] = PI - Ang[i][0];
            Ang[i][1] = PI - Ang[i][1];
        }
        pos[++cnt] = Ang[i][0];
        pos[++cnt] = Ang[i][1];
    }

    sort(pos + 1, pos + 1 + cnt);

    rep(i, 1, n) {
        E[i].x = lower_bound(pos + 1, pos + 1 + cnt, Ang[i][0]) - pos;
        E[i].y = lower_bound(pos + 1, pos + 1 + cnt, Ang[i][1]) - pos;
        if(Cross(B - A, a[i] - A) > 0) E[i].add = 0;
        else E[i].add = 1;
    }

    sort(E + 1, E + 1 + n);

    rep(i, 1, n) {
        if(E[i].add == 0) ans += sum(E[i].y - 1);
        if(E[i].add == 1) add(E[i].y, 1);
    }
    return ans;
}

Point A, B;

int main() {
    scanf("%d", &n);
    scanf("%lld %lld %lld %lld", &A.x, &A.y, &B.x, &B.y);
    rep(i, 1, n) scanf("%lld %lld", &a[i].x, &a[i].y);
    res = solve1(A, B) + solve1(B, A) + solve2(A, B);
    printf("%lld\n", res);
    return 0;
}
View Code

 

标签:偏序,练习赛,return,Point,LL,get,pos,Ang,几何
来源: https://www.cnblogs.com/Willems/p/12628567.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有