BZOJ5317 JSOI2018部落战争(凸包)

  即询问凸包是否有交。这显然可以直接求半平面交,但是复杂度O(q(n+m)),且没有什么优化空间。

  更直接地表示,即相当于询问是否存在点a∈A,b∈B,使得a+d=b。移项,得到d=b-a。可以发现等式右边是一个闵可夫斯基和。求闵可夫斯基和只需要分别求出两个凸包,然后每次考虑ai+1+bi和ai+bi+1哪个将作为凸包中下一个点。将其求出后,只需要判断点是否在凸包内。二分找到上下边界即可。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<cassert>
using namespace std;
#define ll long long
#define vector point
#define N 200010
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
    int x=0,f=1;char c=getchar();
    while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
    while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
    return x*f;
}
int n,m,q;
const double eps=1E-8;
struct point
{
    int x,y;
    vector operator +(const vector&a) const
    {
        return (vector){x+a.x,y+a.y};
    }
    vector operator -(const vector&a) const
    {
        return (vector){x-a.x,y-a.y};
    }
    ll operator *(const vector&a) const
    {
        return 1ll*x*a.y-1ll*y*a.x;
    }
    bool operator <(const point&a) const
    {
        return x<a.x||x==a.x&&y<a.y;
    }
}a[N],b[N],c[N],d[N],e[N],f[N];
struct line
{
    point a;vector p;
    double f(int x){return a.y+(double)(x-a.x)/p.x*p.y;}
};
void makehull(point *hull,point *a,int &n)
{
    sort(a+1,a+n+1);hull[1]=a[1];
    int m=1;
    for (int i=2;i<=n;i++)
    {
        while (m>1&&(a[i]-hull[m-1])*(hull[m]-hull[m-1])>0) m--;
        hull[++m]=a[i];
    }
    for (int i=n-1;i>=1;i--)
    {
        while (m>1&&(a[i]-hull[m-1])*(hull[m]-hull[m-1])>0) m--;
        hull[++m]=a[i];
    }
    n=m;
}
void merge(point *up,point *down,point *a,point *b,int &n,int &m)
{
    int p=1,u=1,v=1;up[1]=a[1]+b[1];
    while (u<n||v<m)
    {
        if (u==n) v++;
        else if (v==m) u++;
        else if ((a[u+1]+b[v]-up[p])*(a[u]+b[v+1]-up[p])>0) u++;else v++;
        while (p>1&&(a[u]+b[v]-up[p-1])*(up[p]-up[p-1])>0) p--;
        up[++p]=a[u]+b[v];
    }
    for (int i=1;i<=p;i++) if (up[i].x>up[i+1].x) {n=i;break;}
    for (int i=n;i<=p;i++) down[i-n+1]=up[i];m=p-n+1;
}
int main()
{
#ifndef ONLINE_JUDGE
    freopen("bzoj5317.in","r",stdin);
    freopen("bzoj5317.out","w",stdout);
#endif
    n=read(),m=read(),q=read();
    for (int i=1;i<=n;i++) a[i].x=read(),a[i].y=read();
    for (int i=1;i<=m;i++) b[i].x=-read(),b[i].y=-read();
    makehull(c,a,n),makehull(d,b,m);
    merge(e,f,c,d,n,m);reverse(f+1,f+m+1);
    for (int i=1;i<=q;i++)
    {
        int x=read(),y=read();
        int u=lower_bound(e+1,e+n+1,(point){x,y})-e;
        if (u==1||u==n+1||(line){e[u-1],e[u]-e[u-1]}.f(x)-eps>y) {printf("0\n");continue;}
        u=lower_bound(f+1,f+m+1,(point){x,y})-f;
        if (u==1||u==m+1||(line){f[u-1],f[u]-f[u-1]}.f(x)+eps<y) {printf("0\n");continue;}
        printf("1\n");
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Gloid/p/10257161.html