zoukankan      html  css  js  c++  java
  • 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
    ");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
    ");continue;}
            printf("1
    ");
        }
        return 0;
    }
  • 相关阅读:
    POJ 2752 Seek the Name, Seek the Fame
    POJ 2406 Power Strings
    KMP 算法总结
    SGU 275 To xor or not to xor
    hihocoder 1196 高斯消元.二
    hihoCoder 1195 高斯消元.一
    UvaLive 5026 Building Roads
    HDU 2196 computer
    Notions of Flow Networks and Flows
    C/C++代码中的笔误
  • 原文地址:https://www.cnblogs.com/Gloid/p/10257161.html
Copyright © 2011-2022 走看看