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\n", res[i]);
}

原文地址:https://www.cnblogs.com/st1vdy/p/11664520.html

时间: 2024-10-15 17:43:17

Codeforces Gym 102361A Angle Beats CCPC2019秦皇岛A题 题解的相关文章

codeforces Gym 100187L L. Ministry of Truth 水题

L. Ministry of Truth Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100187/problem/K Description Andrey works in the Ministry of Truth. His work is changing articles in newspapers and magazines so that they praise the Party an

Codeforces Gym 100610 Problem E. Explicit Formula 水题

Problem E. Explicit Formula Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100610 Description Consider 10 Boolean variables x1, x2, x3, x4, x5, x6, x7, x8, x9, and x10. Consider all pairs and triplets of distinct variables amon

Codeforces Gym 100342H Problem H. Hard Test 构造题,卡迪杰斯特拉

Problem H. Hard TestTime Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100342/attachments Description Andrew is having a hard time preparing his 239-th contest for Petrozavodsk. This time the solution to the problem is based on Di

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[max

Codeforces Round #530 (Div. 2) (前三题题解)

总评 今天是个上分的好日子,可惜12:30修仙场并没有打... A. Snowball(小模拟) 我上来还以为直接能O(1)算出来没想到还能小于等于0的时候变成0,那么只能小模拟了.从最高的地方进行高度的模拟,如果遇到石头就去判断一下会不会小于0其他没有什么好说的了 代码 #include <bits/stdc++.h> using namespace std; int main() { ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); int

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\) 指

[CCPC2019秦皇岛] F. Forest Program

[CCPC2019秦皇岛 F] Link https://codeforces.com/gym/102361/problem/F Description 给定一个仙人掌,删去一些边可以让它变成一个森林(一棵树也是森林),求方案数. \(n \le 300000, m \le 500000\) Solution 用 DFS 暴力找环,然后乘法原理算一下即可.注意非环边也会有贡献. DFS 可以模仿 Tarjan 算法写. Code #include <bits/stdc++.h> using n

[CCPC2019秦皇岛] E. Escape

[CCPC2019秦皇岛E] Escape Link https://codeforces.com/gym/102361/problem/E Solution 观察到性质若干然后建图跑最大流即可. 我的 ISAP 被卡了,换成 Dinic 却过了. #include <bits/stdc++.h> using namespace std; const int maxn = 200005; const int inf = 1e+9; #define reset(x) memset(x,0,siz

Codeforces gym Hello 2015 Div1 B and Div2 D

Codeforces gym 100571 problem D Problem 给一个有向图G<V,E>和源点S,边的属性有长度L和颜色C,即E=<L,C>.进行Q次询问,每次给定一个点X,输出S到X的最短路的长度(不存在则输出 -1).但要求S到X的路径中相邻两条边颜色不一样. Limits Time Limit(ms): 1000 Memory Limit(MB): 256 |V|, |E|: [1, 10^5] X, S: [1, |V| ] L: [1, 10^9] |C|