zoukankan      html  css  js  c++  java
  • [JSOI2018]战争

    题目

    闵可夫斯基和啊

    定义点集(A)和点集(B)的闵可夫斯基和为({a+b|ain A,bin B})

    下面只讨论凸包的闵可夫斯基和

    由于凸包的凸性,所以两个凸包的闵可夫斯基和等价于把其中一个凸包绕另一个凸包的边移动的过程中扫过的区域,更强的性质是,两个闵可夫斯基和与它们的每一条边按极角序顺次相连所得的图形都是等价的,于是我们把两个凸包的左下角加起来,这就是新的凸包的左下角;之后把两个凸包的边都搞出来,按照极角序归并就好了

    可能有三点共线的情况,于是可以对新得到的点再求一个凸包

    对于这道题,移动(v)后有交点等价于存在(ain A,bin B)满足(a=b+v),即(a-b=v)

    所以我们可以把(B)上的点取反,求一下闵可夫斯基和,之后只需要判断(v)是否在这个凸包里就好了

    判断一个点是否在凸包里我们可以二分找到最后一个极角序小于它的点,之后用叉积判断就好了

    代码

    #include<bits/stdc++.h>
    #define re register
    #define LL long long
    inline LL read() {
    	char c=getchar();LL x=0,r=1;while(c<'0'||c>'9'){if(c=='-')r=-1;c=getchar();}
    	while(c>='0'&&c<='9')x=(x<<3ll)+(x<<1ll)+c-48,c=getchar();return x*r;
    }
    const int maxn=1e5+5;
    int n,m,q,len,top;
    struct node{LL x,y;}a[maxn],b[maxn],c[maxn<<1],st[maxn<<1],va[maxn],vb[maxn],T,K;
    inline node operator+(node A,node B){return (node){A.x+B.x,A.y+B.y};}
    inline node operator-(node A,node B) {return (node){A.x-B.x,A.y-B.y};}
    inline LL operator*(node A,node B) {return A.x*B.y-A.y*B.x;}
    inline LL Len(node A) {return A.x*A.x+A.y*A.y;}
    inline int cmp(node A,node B) {return (A-T)*(B-T)==0?Len(A-T)<Len(B-T):(A-T)*(B-T)>0;}
    inline void Get(node *A,int n) {
    	top=0;T.x=1e18,T.y=1e18;
    	for(re int i=1;i<=n;i++) {
    		if(A[i].x<T.x) T=A[i];
    		else if(A[i].x==T.x&&A[i].y<T.y) T=A[i];
    	}
    	std::sort(A+1,A+n+1,cmp);st[top=1]=A[1];
    	for(re int i=2;i<=n;i++) {
    		while(top>1&&(A[i]-st[top-1])*(st[top]-st[top-1])>=0) --top;
    		st[++top]=A[i];
    	}
    	for(re int i=1;i<=top;i++) A[i]=st[i];
    }
    inline void minkowski(node *A,node *B,int n,int m) {
    	for(re int i=1;i<n;i++) va[i]=A[i+1]-A[i];va[n]=A[1]-A[n];
    	for(re int i=1;i<m;i++) vb[i]=B[i+1]-B[i];vb[m]=B[1]-B[m];
    	c[top=1]=A[1]+B[1];int ta=1,tb=1;
    	while(ta<=n&&tb<=m) c[top+1]=c[top]+(va[ta]*vb[tb]>=0?va[ta++]:vb[tb++]),++top;
    	while(ta<=n) c[top+1]=c[top]+va[ta++],++top;
    	while(tb<=m) c[top+1]=c[top]+vb[tb++],++top;
    }
    inline int in(node dr,node *A) {
    	if(dr*A[1]>0||A[len]*dr>0) return 0;
    	int l=1,r=len,nw=0;T.x=0,T.y=0;
    	while(l<=r) {
    		int mid=l+r>>1;
    		if(cmp(A[mid],dr)) nw=mid,l=mid+1;else r=mid-1;
    	}
    	return (dr-A[nw])*(A[nw%len+1]-A[nw])<=0;
    }
    int main() {
    	n=read();m=read(),q=read();
    	for(re int i=1;i<=n;i++) a[i].x=read(),a[i].y=read();
    	for(re int i=1;i<=m;i++) b[i].x=-read(),b[i].y=-read();
    	Get(a,n);n=top;Get(b,m),m=top;
    	minkowski(a,b,n,m);len=top;Get(c,len);len=top;
    	for(re int i=len;i>1;i--) c[i]=c[i]-c[1];K=c[1];c[1]=c[1]-c[1];
    	for(node dr;q;--q) {
    		dr.x=read(),dr.y=read();
    		printf("%d
    ",in(dr-K,c));
    	}
    	return 0;
    }
    
  • 相关阅读:
    深入类的方法
    泛型集合
    深入C#数据类型
    深入.net框架
    错题
    详解Python Graphql
    深入理解分布式调度框架TBSchedule及源码分析
    30分钟闲置服务器建站(gitlab为例)
    Webpack开发指南
    mybatis-generator
  • 原文地址:https://www.cnblogs.com/asuldb/p/12009845.html
Copyright © 2011-2022 走看看