牛客多校第二场 C (计算几何+二分)

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

时间限制:C/C++ 2秒,其他语言4秒
空间限制:C/C++ 262144K,其他语言524288K
Special Judge, 64bit IO Format: %lld

题目描述

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".

示例1

输入

复制

2
0 -1
1 2
3
-1 4
2 -2
2 5

输出

复制

5.000000000000000
4.000000000000000
No cross

说明

 
  
 

计算几何+二分。

可以得知,对于y=ax+b,与y=cx+d,两条直线的交点的横坐标为(d-b)/(a-c)

对a和c取反之后,实际上是可以表示成两个点的斜率

我们可以存下所有的询问,然后用凸包维护。

在维护凸包的过程中用二分找到对于询问的点斜率最大的点。

#include<bits/stdc++.h>
#define mp make_pair
#define fir first
#define se second
#define ll long long
#define pb push_back
using namespace std;
const int maxn=1e5+10;
const ll mod=1e9+7;
const int maxm=1e6+10;
const double eps=1e-7;
const int inf=0x3f3f3f3f;
const double pi = acos (-1.0);
int dcmp ( double x)
{
    if ( fabs (x) < eps) return 0;
    return (x < 0 ? -1 : 1);
}
inline double sqr ( double x)
{
    return x*x;
}
struct Point
{
    double x, y;
    int id;
    Point ( double _x = 0, double _y = 0):x(_x), y(_y) {}
    void input ()
    {
        scanf ( "%lf%lf", &x, &y);
    }
    void output ()
    {
        printf ( "%.2f %.2f\n", x, y);
    }
    bool operator == ( const Point &b) const
    {
        return (dcmp (x-b.x) == 0 && dcmp (y-b.y) == 0);
    }
    bool operator < ( const Point &b) const
    {
        return (dcmp (x-b.x) == 0 ? dcmp (y-b.y) < 0 : x < b.x);
    }
    Point operator + ( const Point &b) const
    {
        return Point (x+b.x, y+b.y);
    }
    Point operator - ( const Point &b) const
    {
        return Point (x-b.x, y-b.y);
    }
    Point operator * ( double a)
    {
        return Point (x*a, y*a);
    }
    Point operator / ( double a)
    {
        return Point (x/a, y/a);
    }
    double len2 ()
    {
        return sqr (x) + sqr (y);
    }
    double len ()
    {
        return sqrt (len2 ());
    }
    Point change_len ( double r)
    {
        double l = len ();
        if (dcmp (l) == 0) return *this;
        r /= l;
        return Point (x*r, y*r);
    }
    Point rotate_left ()
    {
        return Point (-y, x);
    }
    Point rotate_right ()
    {
        return Point (y, -x);
    }
    Point rotate (Point p, double ang)
    {
        Point v = (*this)-p;
        double c = cos (ang), s = sin (ang);
        return Point (p.x + v.x*c - v.y*s, p.y + v.x*s + v.y*c);
    }
    Point normal ()
    {
        double l = len ();
        return Point (-y/l, x/l);
    }
};
double cross (Point a, Point b)
{
    return a.x*b.y-a.y*b.x;
}
double cal(Point a,Point b){
    return (a.y-b.y)/(a.x-b.x);
}
Point p[maxn],ch[maxn];
double ans[maxn];
int n,m;
int num;
int convex_hull (Point *p, Point *ch, int n)
{
    sort (p, p+n);
    int m = 0;
    for ( int i = 0; i < n; i++)
    {
        if (p[i].id){
            int l=0;
            int r=m-1;
            while (l<r){
                int mid=(l+r)>>1;
                if(cross(p[i]-ch[mid],p[i]-ch[mid+1])<=0) r=mid;
                else l=mid+1;
            }
            if (l<m){
                ans[p[i].id]=max(ans[p[i].id],cal(p[i],ch[l]));
            }
            continue;
        }
        while (m > 1 && cross (ch[m-1]-ch[m-2], p[i]-ch[m-1]) <= 0)
            m--;
        ch[m++] = p[i];
    }
    int k = m;
    for ( int i = n-2; i >= 0; i--)
    {
        if (p[i].id){
            int l=k-1;
            int r=m-1;
            while (l<r){
                int mid=(l+r)>>1;
                if(cross(p[i]-ch[mid],p[i]-ch[mid+1])<=0) r=mid;
                else l=mid+1;
            }
            if (l<m){
                ans[p[i].id]=max(ans[p[i].id],cal(p[i],ch[l]));
            }
            continue;
        }
        while (m > k && cross (ch[m-1]-ch[m-2], p[i]-ch[m-1])  <= 0)
            m--;
        ch[m++] = p[i];
    }
    if (n > 1)
        m--;
    return m;
}
int main(){
    cin>>n;
    for (int i=0;i<n;i++){
        p[i].input();
        p[i].x*=-1;   //转化为求最大值
        p[i].id=0;
    }
    cin>>m;
    for (int i=0;i<m;i++){
        p[i+n].input();
        p[i+n].x*=-1;  //转化为求最大值
        p[i+n].id=i+1;
    }
    num=convex_hull(p,ch,n+m);
    for (int i=1;i<=m;i++){
        if (dcmp(ans[i])==0){
            printf("No cross\n");
        }
        else printf("%.15lf\n",ans[i]);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/wyj_alone_smile/article/details/81197137