牛客网多校第二场C—message(计算几何——神奇的转化——凸包)

目录

题目描述

输入描述:

输出描述:

题意:

思路:

解法:

AC代码:

 


链接:https://www.nowcoder.com/acm/contest/140/C
来源:牛客网
 

题目描述

There is an infinite plane. White Cloud has n lines which are not parallel to the Oy axis. These lines in the plane are in the form y=ax+b.
White Rabbit will have a trip in the plane. It will start at time 0 and go straight along a line. specifically, White Rabbit uses 2 parameters C and D,denoting that at time x, White Rabbit is at the position(x,C*x+D).
If at some time, White Rabbit is located at one of White Cloud's lines, White Cloud will receive a message immediately.

White Rabbit has m pairs (C[i],D[i]) for i=1..m. For each i=1..m, White Cloud wants to know if White Rabbit uses (C[i],D[i]) , when is the last time White Cloud can receive a message.

 

输入描述:

The first line of input contains an integer n. (n<=50000)
For the next n lines, the i-th line contains 2 integers A[i], B[i], describing the i-th line. (-1e9<=A[i],B[i]<=1e9)
All numbers A[i] are different.
The next line contains an integer m. (m<=50000)
For the next m lines, the i-th line contains 2 integers C[i],D[i], describing the i-th pair.(-2e9<=C[i],D[i]<=2e9)
Each C[j] is different from any of the numbers A[i].
Each D[j] is different from any of the numbers B[i].

输出描述:

Print m lines. The i-th line contains a real number with at least 6 digits after the decimal point, denoting the latest time White Cloud can receive a message. Your answer must be correct within an absolute error of 1e-6.
If White Cloud can't receive any message during White Rabbit's trip,print a string "No cross".

题意:

大概就是已知n条直线y=a[i]x+b[i],有m次询问,每次给出一条线段y=c[i]x+d[i],问是否有x>0的交点,如果有输出横坐标。

思路

这个题比较巧妙,线段的斜率和截距转换成了两点之间的斜率,然后用凸包求解。

解法

通过y = ax + by = cx + d联立,可以解得x = -\frac{b - d}{a - c},这个题的巧妙之处就在这里,x不正好是点\left (a,b \right )和点\left(c,d\right)连线斜率的相反数吗。将之前输入的所有直线的斜率和截距看成点,然后通过凸包就可以解出最大值了。

AC代码:

#include <bits/stdc++.h>
using namespace std;
const int mod = 1000000007;
const int N =4e5 + 7;
const double ex = 1e-8;
typedef unsigned long long ull;
typedef long long ll;
typedef double dl;
struct Point{
    double x,y;
    int id;
}p[N],u[N];
double ans[N];
int n,m;
bool cmp(Point a,Point b)
{
    if(a.x == b.x)  return a.y < b.y;
    return a.x < b.x;
}
inline double cal(Point a,Point b)
{
    return (b.y - a.y) / (a.x - b.x);
}
void binary_find()
{
    int t = 0;
    for(int i = 0;i < m + n;++i){
        if(p[i].id){
            int l = 1,r = t,mid1,mid2;
            if(!t || p[i].y > u[1].y) continue;
            while(r - l > 2){
                mid1 = (l * 2 + r) / 3;
                mid2 = (l + 2 * r) / 3;
                if(cal(u[mid1],p[i]) > cal(u[mid2],p[i])) r = mid2;
                else l = mid1;
            }
            for(int j = l;j <= r;++j)
                ans[p[i].id]=max(ans[p[i].id],cal(u[j],p[i]));
        }
        else{
            while(t > 0 && p[i].y > u[t].y)    t--;
            while(t > 1 && cal(u[t],p[i]) < cal(u[t - 1],p[i]))  t--;
            if(t == 1 && p[i].y > u[t].y){
                u[t].x = p[i].x;
                u[t].y = p[i].y;
            }
            else{
                u[++t].x = p[i].x;
                u[t].y = p[i].y;
            }
        }
    }
}
int main()
{
    scanf("%d",&n);
    for(int i = 0;i < n;++i)
        scanf("%lf%lf",&p[i].x,&p[i].y);
    scanf("%d",&m);
    for(int i = 0;i < m;++i){
        scanf("%lf%lf",&p[i + n].x,&p[i + n].y);
        p[i + n].id = i + 1;
    }
    sort(p,p + n + m,cmp);
    for(int i = 1;i <= m;++i)   ans[i] = -1.0;
    binary_find();
    for(int i = 0;i < n + m;++i){
        p[i].x *= -1;
        p[i].y *= -1;
    }
    reverse(p,p + n + m);
    binary_find();
    for(int i = 1;i <= m;++i){
        if(ans[i] < 0)  printf("No cross\n");
        else printf("%.10lf\n",ans[i]);
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值