模板题

代码

#include<bits/stdc++.h>
#define N 200010
#define INF 0x3f3f3f3f
#define eps 1e-5
#define pi 3.141592653589793
#define mod 998244353
// #define P 1000000007
#define LL long long
#define pb push_back
#define fi first
#define se second
#define cl clear
#define si size
#define lb lower_bound
#define ub upper_bound
#define bug(x) cerr<<#x<<" : "<<x<<endl
#define mem(x,y) memset(x,0,sizeof(int)*(y+3))
#define sc(x) scanf("%d",&x)
#define scc(x,y) scanf("%d%d",&x,&y)
#define sccc(x,y,z) scanf("%d%d%d",&x,&y,&z)
using namespace std;
typedef  pair<int,int> pp;
struct Point
{
    LL x,y;
    bool operator < (const Point &a)const
    {return (x-a.x)<0 || ((x-a.x)==0 && (y-a.y)<0);}
    Point(LL x=0,LL y=0):x(x),y(y){ }
    void read(){scanf("%lld%lld",&x,&y);}
};
typedef Point Vector;
Vector operator + (Vector a,Vector b){return Vector(a.x+b.x,a.y+b.y);}
Vector operator - (Vector a,Vector b){return Vector(a.x-b.x,a.y-b.y);}
LL Cross(Vector a,Vector b){return a.x*b.y-a.y*b.x;}
LL Dot(Vector a,Vector b){return a.x*b.x+a.y*b.y;}  //点积
//凸包
/*************************************************************** * 输入点数组p, 个数为p, 输出点数组ch。 返回凸包顶点数 * 希望凸包的边上有输入点,把两个<= 改成 < * 高精度要求时建议用dcmp比较 * 输入点不能有重复点。函数执行完以后输入点的顺序被破坏 ****************************************************************/
int ConvexHull(Point *p, int n, Point* ch) {
    sort(p, p+n);      //先比较x坐标,再比较y坐标
    int m = 0;
    for(int i = 0; i < n; i++) {
        while(m > 1 && Cross(ch[m-1] - ch[m-2], p[i]-ch[m-2]) <= 0) m--;
        ch[m++] = p[i];
    }
    int k = m;
    for(int i = n-2; i >= 0; i--) {
        while(m > k && Cross(ch[m-1] - ch[m-2], p[i]-ch[m-2]) <= 0) m--;
        ch[m++] = p[i];
    }
    if(n > 1) m--;
    return m;
}
//点在线段上(包含端点),在为 1 ,不在为 0
bool isPointOnSegment(Point P,Point A,Point B)
{
    return (Cross(A-P,B-P))==0 && (Dot(A-P,B-P))<=0;  // 不包含端点时为 <0
}
//判断点在凸包内模板 O(logn)
//凸包为逆时针
//在边界,返回0,在内部,返回1,在外部,返回-1
int check(Point A,Point*p,int n )
{
    if (isPointOnSegment(A,p[0],p[1])) return 0; // 包含端点
    if (isPointOnSegment(A,p[0],p[n-1])) return 0;
    int l=1,r=n-2,mid;
    while(l<=r)
    {
        mid=(l+r)>>1;
        LL a1=Cross(p[mid]-p[0],A-p[0]);
        LL a2=Cross(p[mid+1]-p[0],A-p[0]);
        if(a1>=0&&a2<=0)
        {
            LL tmp=Cross(p[mid+1]-p[mid],A-p[mid]);
            if (tmp>0)return 1;
            if (tmp==0) return 0;
            return -1;
        }
        else if(a1<0)r=mid-1;else l=mid+1;
    }
    return -1;
}

Point a[N],b[N],c[N];
int Minkowski(Point *a,int n,Point *b,int m,Point *c){
    int t=0,x=1,y=1;
    c[t++]=a[0]+b[0]; a[n]=a[0],b[m]=b[0];
    while(x<=n&&y<=m)
        if (Cross(a[x]-a[x-1],b[y]-b[y-1])>0) 
            c[t]=c[t-1]+a[x]-a[x-1],t++,x++;
        else
            c[t]=c[t-1]+b[y]-b[y-1],t++,y++;
    while(x<=n) c[t]=c[t-1]+a[x]-a[x-1],t++,x++;
    while(y<=m) c[t]=c[t-1]+b[y]-b[y-1],t++,y++;
    return t-1;
}

int main(int argc, char const *argv[])
{
    int n,m,q;
    sccc(n,m,q);
    for(int i=0;i<n;i++) a[i].read();
    for(int i=0;i<m;i++) b[i].read(),b[i].x*=-1,b[i].y*=-1;
    n=ConvexHull(a,n,c);
    memcpy(a,c,sizeof(Point)*(n));
    m=ConvexHull(b,m,c);
    memcpy(b,c,sizeof(Point)*(m));
    int p=Minkowski(a,n,b,m,c);
    while(q--){
        Point x; x.read();
        int t=check(x,c,p);
        if (t==-1) puts("0");else puts("1");
    }
    return 0;
}