牛客网多校第二场C—message

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/leekerian/article/details/81990379

鬼知道我经理了什么,这题嗯是的写了一个星期,,,,

用凸包来维护斜率,说几个点,1为什么要离线,因为如果你不把询问的点加进去构造凸包的话你用原来构造的凸包并不一定是解

所以很巧妙的离线构造,当询问到点是那个点的左边已经是构造好的凸包了只要访问凸包上的点就可以了,右边也是一样的

还有注意0.000000

#include <iostream>
#include <cmath>
#include <cstdio>
#include <algorithm>

using namespace std;

const int maxn=66666;
const double eps=1e-8;

int sgn(double x)
{
    if(fabs(x)<eps)
        return 0;
    if(x<0)
        return -1;
    else
        return 1;
}

struct Point
{
    double x,y;
    int fl;
    int index;
    double ans;
    Point(){}
    Point(double _x,double _y)
    {
        x=_x;
        y=_y;
    }
    Point operator -(const Point &b)const
    {
        return Point(x-b.x,y-b.y);
    }
    double operator ^(const Point &b)const
    {
        return x*b.y-y*b.x;
    }
    double operator *(const Point &b)const
    {
        return x*b.x+y*b.y;
    }
};

Point p[maxn];
Point p1[maxn];
int n;
int Stack[maxn];
int top;

bool cmp(Point a,Point b)
{
    if(a.x!=b.x)
        return a.x<b.x;
    else
        return a.y>b.y;
}


void anderw(int n)
{
    sort(p,p+n,cmp);
    top=0;
    for(int i=0;i<n;i++)
    {
        if(p[i].fl==1)
        {
            if(top==0)
                continue;
            int l=0;
            int r=top-1;
            int mid;
            while(l<=r)
            {
                mid=(l+r)>>1;
                int ans1=sgn((p[Stack[mid]]-p[i])^(p[Stack[0]]-p[i]));
                if(ans1>=0)
                    l=mid+1;
                else
                    r=mid-1;
            }
            mid=(l+r)>>1;
            while(mid>0&&sgn((p[Stack[mid]]-p[i])^(p[Stack[mid-1]]-p[i]))<=0)
            {
                p[i].ans=max(p[i].ans,(-(p[Stack[mid]].y-p[i].y)/(p[Stack[mid]].x-p[i].x)));
                mid=mid-1;
            }
            p[i].ans=max(p[i].ans,(-(p[Stack[mid]].y-p[i].y)/(p[Stack[mid]].x-p[i].x)));
        }
        else
        {
            while(top>1&&sgn((p[Stack[top-1]]-p[Stack[top-2]])^(p[i]-p[Stack[top-2]]))>=0)
                top--;
            Stack[top++]=i;
        }
    }
    //for(int i=0;i<top;i++)
        //cout<<p[Stack[i]].x<<"*"<<p[Stack[i]].y<<endl;
    top=0;

    for(int i=n-1;i>=0;i--)
    {
        if(p[i].fl==1)
        {
            if(top==0)
                continue;
            int l=0;
            int r=top-1;
            int mid;
            while(l<=r)
            {
                mid=(l+r)>>1;
                if(sgn((p[Stack[mid]]-p[i])^(p[Stack[0]]-p[i]))>=0)
                    l=mid+1;
                else
                    r=mid-1;
            }
            mid=(l+r)/2;
            while(mid>0&&sgn((p[Stack[mid]]-p[i])^(p[Stack[mid-1]]-p[i]))<=0)
            {
                //cout<<p[Stack[mid]].x<<" "<<p[Stack[mid]].y<<endl;
                p[i].ans=max(p[i].ans,(-(p[Stack[mid]].y-p[i].y)/(p[Stack[mid]].x-p[i].x)));
                mid=mid-1;
            }
            p[i].ans=max(p[i].ans,(-(p[Stack[mid]].y-p[i].y)/(p[Stack[mid]].x-p[i].x)));
        }
        else
        {
            while(top>1&&sgn((p[Stack[top-1]]-p[Stack[top-2]])^(p[i]-p[Stack[top-2]]))>=0)
                top--;
            Stack[top++]=i;
        }
    }
    //for(int i=0;i<top;i++)
       // cout<<p[Stack[i]].x<<"*"<<p[Stack[i]].y<<endl;
    /*for(int i=k-1;i<top;i++)
        cout<<p[Stack[i]].x<<" "<<p[Stack[i]].y<<endl;
    */
}


bool cmp1(Point a,Point b)
{
    return a.index<b.index;
}

int main()
{
    cin>>n;
    for(int i=0;i<n;i++)
    {
        scanf("%lf %lf",&p[i].x,&p[i].y);
        p[i].fl=0;
        p[i].index=i;
    }
    int m;
    cin>>m;
    for(int i=n;i<(n+m);i++)
    {
        scanf("%lf %lf",&p[i].x,&p[i].y);
        p[i].index=i;
        p[i].fl=1;
        p[i].ans=-1;
    }
    anderw(n+m);
    sort(p,p+n+m,cmp1);
    for(int i=n;i<n+m;i++)
    {
        if(p[i].ans<=0)
            cout<<"No cross"<<endl;
        else
            printf("%.12lf\n",p[i].ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/leekerian/article/details/81990379