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

Posted st1vdy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces Gym 102361A Angle Beats CCPC2019秦皇岛A题 题解相关的知识,希望对你有一定的参考价值。

题目链接https://codeforces.com/gym/102361/problem/A

题意:给定二维平面上的(n)个点,(q)次询问,每次加入一个点,询问平面上有几个包含该点的直角三角形。

分析:这是一篇鸽了很久的题解,主要原因就是现场赛的时候这题惨遭卡常,锅++。现在回过头来想这题,主要问题出在现场赛时误判了(map)的时间复杂度,把极角排序的正确想法成功叉掉,以及现场赛时候的共线计数使用了(gcd),使得整体复杂度上升。(但还是有大佬拿gcd思想过了,我太菜了)现在学了一种共线计数的新想法,只需要重载就能实现,于是再用(map)来写一写这道题。。。

本题思路不难,将直角三角形分为两类,一类是以新加入点为直角顶点的直角三角形,另一类新加入点不作直角顶点。第一种情况,我们将新加入点与原有点之间构成的所有向量加入(map),然后通过点积为零的性质查找垂直的向量个数。(会计数两次,要除以二)另一类采取离线操作,我们将每个原有点当作直角顶点遍历,并将该点与另外原有点构成的向量加入(map),更新(q)个新加入点的直角三角形数量即可。

AC代码

#pragma GCC target("avx")
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
#define SIZE 2010
#define rep(i, a, b) for (int i = a; i <= b; ++i)
#define ll long long
using namespace std;
struct Point {
    ll x, y;
    Point() {}
    Point(ll a, ll b) :x(a), y(b) {}
    Point base() const{
        if (x < 0 || (x == 0 && y < 0))return Point(-x, -y);
        return *this;
    }
    bool operator<(const Point& b)const {
        Point p1 = base(); Point p2 = b.base(); //如果共线,考虑是相同的索引
        return p1.x * p2.y < p1.y * p2.x;
    }
    void input() { scanf("%lld %lld", &x, &y); }
}p[SIZE];
Point operator *(Point a, ll t) { return Point(a.x * t, a.y * t); }            //向量数乘
Point operator +(Point a, Point b) { return Point(a.x + b.x, a.y + b.y); }    //向量加法
Point operator -(Point a, Point b) { return Point(b.x - a.x, b.y - a.y); }    //向量减法
Point operator / (Point a, ll p) { return Point(a.x / p, a.y / p); }    //向量数乘的除法形式
double Polarangle(Point a) { return atan2(a.y, a.x); }
ll __gcd(ll a, ll b) { return b == 0 ? a : __gcd(b, a % b); }
int n, q, cnt = 1;
map<Point, int> MAP;
int main() {
    scanf("%d %d", &n, &q);
    int m = q;
    vector<Point> vec(q + 1);
    vector<int> res(q + 1);
    rep(i, 1, n) p[i].input();
    while (m--) {
        int ans = 0; Point tp; tp.input();
        vec[cnt] = tp;
        rep(i, 1, n) {
            Point tmp = p[i] - tp;
            ++MAP[tmp];
        }
        for (auto it : MAP) {
            Point tmp(-it.first.y, it.first.x);
            if (MAP.count(tmp)) ans += MAP[tmp] * it.second;
        }
        res[cnt++] = ans / 2;
        MAP.clear();
    }
    rep(i, 1, n) {
        MAP.clear();
        rep(j, 1, n) {
            if (i == j) continue;
            MAP[p[j] - p[i]]++;
        }
        rep(j, 1, q) {
            Point tp = vec[j] - p[i];
            tp = Point(-tp.y, tp.x);
            res[j] += MAP.count(tp) ? MAP[tp] : 0;
        }
    }
    rep(i, 1, q) printf("%d
", res[i]);
}

以上是关于Codeforces Gym 102361A Angle Beats CCPC2019秦皇岛A题 题解的主要内容,如果未能解决你的问题,请参考以下文章

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

Codeforces Gym 100269 Dwarf Tower (最短路)

codeforces Gym 101063 C

codeforces Gym 100735 DEGHI

CodeForces Gym-101350M

Codeforces-gym-101020 problem C. Rectangles