栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

18牛客暑假多校C(计算几何)

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

18牛客暑假多校C(计算几何)

题目大意:

n ( ≤ 50000 ) n(le 50000) n(≤50000)条直线( y = a x + b y=ax+b y=ax+b), m ( ≤ 50000 ) m(le 50000) m(≤50000)个询问,每次询问给出一条直线: y = c x + d y=cx+d y=cx+d,询问这条直线和 n n n条直线交点最远的点的横坐标(答案必须大于等于0)

解题思路:
  • 相交的点为如下方程:
    a x + b = c x + d x = b − d c − a → x = b − d − a − ( − c ) ax+b=cx+d \ x=frac{b-d}{c-a} rightarrow x=frac{b-d}{-a-(-c)} \ ax+b=cx+dx=c−ab−d​→x=−a−(−c)b−d​

  • 问题就变成了有 n ( − a , b ) n(-a,b) n(−a,b)个点,每次询问给出一个点 ( − c , d ) (-c,d) (−c,d),求斜率最大值

  • 可以分成两段来看,先看 − c -c −c左边的点,将这些点构成凸包,之后在凸包上二分即可,右边同理

AC代码:
#include 
#define ft first
#define sd second
#define pb push_back
#define IOS ios::sync_with_stdio(false), cin.tie(0), cout.tie(0) //不能跟puts混用
#define seteps(N) fixed << setprecision(N)
#define endl "n"
const int maxn = 1e5 + 10;
using namespace std;
typedef long long ll;
typedef double db;
typedef pair pii;
const ll mod = 1e9 + 7;
const db eps = 1e-8;
int sgn(db x) {
    if (fabs(x) < eps) return 0;
    else return x < 0 ? -1 : 1;
}
int n, m;
struct Point {
    db x, y;
    int id;
    db operator ^ (Point p) {return x * p.y - y * p.x;}
    Point operator - (Point p) {return {x - p.x, y - p.y};}
    bool operator < (Point p) {
        if (sgn(x - p.x)) return x < p.x;
        else return y < p.y;
    }
} p[maxn], t[maxn];
int cross(Point p1, Point p2, Point p3) {return sgn((p2 - p1) ^ (p3 - p1));}
int cnt = 0;
db ans[maxn];
void solve() {
    cnt = 0;
    for (int i = 1; i <= n + m; i++) {
        if (p[i].id) {
            if (!cnt) continue;
            int l = 1, r = cnt, m;
            while (l < r) {
                m = l + r >> 1;
                if (cross(t[m], t[m + 1], p[i]) > 0) l = m + 1; //利用叉积来找最大的哪个斜率
                //画下图可以知道,斜率最大的那个点,必然跟凸包相切,那么cross叉积就小于0,且上一个点叉积大于0
                else r = m;
            }
            ans[p[i].id] = max(ans[p[i].id], (p[i].y - t[l].y) / (p[i].x - t[l].x));
        }
        else {
            while (cnt > 1 && cross(t[cnt - 1], t[cnt], p[i]) <= 0) cnt--;
            t[++cnt] = p[i];
        }
    }
}
void print() {
    for (int i = n + 1; i <= n + m; i++)
        if (sgn(ans[i]) <= 0) cout << "No cross" << endl;
        else cout << seteps(10) << ans[i] << endl;
}
int main() {
    IOS;
    cin >> n;
    for (int i = 1; i <= n; i++) cin >> p[i].x >> p[i].y, p[i].x = -p[i].x;
    cin >> m;
    for (int i = n + 1; i <= n + m; i++) cin >> p[i].x >> p[i].y, p[i].id = i, p[i].x = -p[i].x;
    sort (p + 1, p + n + m + 1);
    solve();
    reverse(p + 1, p + n + m + 1);//翻转
    solve();
    print();
    return 0;
}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/290172.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号