【雅礼同考9.9】Triangle

版权声明:本文为蒟蒻所写,神犇转载尽情拍打喂食虐待,如发现任何的辣鸡错误欢迎吐槽! https://blog.csdn.net/HOWARLI/article/details/82669807

Description

给出一些在二维平面中第一象限的点,
有多个询问,每次给出两个点(x,y),(x1,y1),要求顶点为(0,0),(x,y),(x1,y1)的三角形内是否有点,

Solution

我们分别过点(x,y),(0,0)和(0,0),(x1,y1)作两直线,把两直线之间的点挑出来,
显然的,如果三角形内存在点,那么一定在凸包上,
那么我们维护区间凸包即可,

复杂度: O ( n log 2 ( n ) )

Code

#include <cstdio>
#include <algorithm>
#include <cmath>
#define fo(i,a,b) for(int i=a;i<=b;++i)
#define fod(i,a,b) for(int i=a;i>=b;--i)
#define efo(i,q) for(int i=A[q];i;i=B[i][0])
#define min(q,w) ((q)>(w)?(w):(q))
#define max(q,w) ((q)<(w)?(w):(q))
#define CJ1(q,w,x,y) ((LL)(w)*(x)-(LL)(q)*(y)>0)
#define CJ(q,w,x,y) (((LL)(w)*(LL)(x)-(LL)(q)*(LL)(y))>=0)
using namespace std;
typedef long long LL;
const int N=100500;
int read(int &n)
{
    char ch=' ';int q=0,w=1;
    for(;(ch!='-')&&((ch<'0')||(ch>'9'));ch=getchar());
    if(ch=='-')w=-1,ch=getchar();
    for(;ch>='0' && ch<='9';ch=getchar())q=q*10+ch-48;n=q*w;return n;
}
int m,n,ans;
int a1[N][2],a0[N][2];
struct VAL
{
    int x,y;
}a[N];
bool PX(VAL q,VAL w){return CJ1(q.x,q.y,w.x,w.y);}
int d[N*20][2],d0,d1[N*20][2],d01;
int zx[N*4][2],zx1[N*4][2];
int CC;
void build(int l,int r,int e)
{
    if(l==r)
    {
        zx[e][0]=zx[e][1]=++d0;
        zx1[e][0]=zx1[e][1]=++d01;
        d1[d01][0]=d[d0][0]=a[l].x;
        d1[d01][1]=d[d0][1]=a[l].y;
        return;
    }
    int mid=(l+r)>>1;
    build(l,mid,e<<1);
    build(mid+1,r,e<<1|1);
    int i=l,j=mid+1,k=1;
    for(;i<=mid||j<=r;++k)
    {
        if(j>r||(i<=mid&&(a[i].x<a[j].x||(a[i].x==a[j].x&&a[i].y<a[j].y))))
        {
            a1[k][0]=a[i].x,a1[k][1]=a[i].y;
            ++i;
        }else a1[k][0]=a[j].x,a1[k][1]=a[j].y,++j;
    }
    zx[e][0]=d0+1;
    fo(i,l,r)
    {
        a[i].x=a1[i-l+1][0],a[i].y=a1[i-l+1][1];
        if(i>l&&a[i].x==a[i-1].x)continue;
        for(;d0>zx[e][0]&&CJ(d[d0][0]-a[i].x,d[d0][1]-a[i].y,d[d0][0]-d[d0-1][0],d[d0][1]-d[d0-1][1]);--d0);
        d[++d0][0]=a[i].x;
        d[d0][1]=a[i].y;
    }
    zx[e][1]=d0;
    zx1[e][0]=d01+1;
    fo(i,l,r)
    {
        for(;d01>zx1[e][0]&&CJ(a[i].x-d1[d01][0],a[i].y-d1[d01][1],d1[d01][0]-d1[d01-1][0],d1[d01][1]-d1[d01-1][1]);--d01)
        d1[++d01][0]=a[i].x;
        d1[d01][1]=a[i].y;
    }
    zx1[e][1]=d01;
}
LL X2,Y2,X1,Y1;
bool Ks;
bool CEK(int e)
{
    if(Ks)
    {
        int l=zx[e][0],r=zx[e][1]-1;
        for(;l<r;)
        {
            int mid=(l+r)>>1;
            if(CJ(X2-X1,Y2-Y1,d[mid+1][0]-d[mid][0],d[mid+1][1]-d[mid][1]))l=mid+1;
            else r=mid;
        }
        return CJ(d[l][0]-X2,d[l][1]-Y2,X1-X2,Y1-Y2)||((l<=r)&&CJ(d[l+1][0]-X2,d[l+1][1]-Y2,X1-X2,Y1-Y2));
    }
    int l=zx1[e][0],r=zx1[e][1]-1;
    for(;l<r;)
    {
        int mid=(l+r)>>1;
        if(CJ(d1[mid+1][0]-d1[mid][0],d1[mid+1][1]-d1[mid][1],X1-X2,Y1-Y2))l=mid+1;
        else r=mid;
    }
    return CJ(d1[l][0]-X2,d1[l][1]-Y2,X1-X2,Y1-Y2)||((l<=r)&&CJ(d1[l+1][0]-X2,d1[l+1][1]-Y2,X1-X2,Y1-Y2));
}
bool find(int l,int r,int e)
{
    if(CJ(X1,Y1,a0[l][0],a0[l][1])&&CJ(a0[r][0],a0[r][1],X2,Y2))return CEK(e);
    if(l==r)return 0;
    int mid=(l+r)>>1;
    bool ans=0;
    if(CJ(X1,Y1,a0[mid][0],a0[mid][1]))ans=find(l,mid,e<<1);
    if(ans)return 1;
    return (CJ(a0[mid+1][0],a0[mid+1][1],X2,Y2))?find(mid+1,r,e<<1|1):0;
}
int main()
{
    int q,w;
    read(n),read(m);
    fo(i,1,n)
    {
        read(a[i].x),read(a[i].y);
    }
    sort(a+1,a+1+n,PX);
    fo(i,1,n)a0[i][0]=a[i].x,a0[i][1]=a[i].y;
    build(1,n,1);
    fo(I,1,m)
    {
        X1=read(q),Y1=read(q),X2=read(q),Y2=read(q);
        if(CJ(X2,Y2,X1,Y1))swap(X1,X2),swap(Y1,Y2);
        Ks=CJ(0,1,X2-X1,Y2-Y1);

        ans=find(1,n,1);
        if(ans)printf("Y\n");
        else printf("N\n");
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/HOWARLI/article/details/82669807