P4557 [JSOI2018]战争

P4557 [JSOI2018]战争

链接

P4557 [JSOI2018]战争

题解

闵可夫斯基和的板子题。
题目给了两个点集(A),(B),显然可以先把凸包搞出来。。
然后多次询问,每次询问一个向量是否满足存在 (b+w) (=) (a)
移项之后就是问是否满足存在(w=a-b) ,把(B)中的每个点坐标取反,然后求闵可夫斯基和就可以了。

(Code)

#include <bits/stdc++.h>
#define LL long long
using namespace std;
const int N=2e5+10;
int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
void print(LL x){
    if(x>9) print(x/10);
    putchar(x%10+'0');
}

struct P{
	LL x,y;
	LL len(){return x*x+y*y;}
	P(LL xx=0,LL yy=0){x=xx;y=yy;}
};
P operator - (P x,P y){return P(x.x-y.x,x.y-y.y);}
P operator + (P x,P y){return P(x.x+y.x,x.y+y.y);}
LL operator * (P x,P y){return x.x*y.y-x.y*y.x;}

bool cmp1(P x,P y){return x.y<y.y||(x.y==y.y&&x.x<y.x);}
bool cmp2(P x,P y){return x*y>0||(x*y==0&&x.len()<y.len());}
void Convex(P *A,int &n){
	sort(A+1,A+1+n,cmp1);
	P O=A[1];
	for(int i=2;i<=n;++i){
		A[i]=A[i]-A[1];
	}
	sort(A+2,A+1+n,cmp2);
	int tp=1;
	for(int i=2;i<=n;++i){
		while(tp>=3&&((A[i]-A[tp-1])*(A[tp]-A[tp-1])>=0)) --tp;
		A[++tp]=A[i];
	}
	n=tp;
	for(int i=2;i<=n;++i) A[i]=A[i]+O;
	return;
}
P D[N];

int tot;
int n,m,Q; 
P C1[N],C2[N],a1[N],a2[N];
void Minkowski(){
	for(int i=1;i<n;++i) a1[i]=C1[i+1]-C1[i];a1[n]=C1[1]-C1[n];
	for(int i=1;i<m;++i) a2[i]=C2[i+1]-C2[i];a2[m]=C2[1]-C2[m];
	D[tot=1]=C1[1]+C2[1];
	LL p1=1,p2=1;
	while(p1<=n&&p2<=m) ++tot,D[tot]=D[tot-1]+(a1[p1]*a2[p2]>=0?a1[p1++]:a2[p2++]);
	while(p1<=n) ++tot,D[tot]=D[tot-1]+a1[p1++];
	while(p2<=m) ++tot,D[tot]=D[tot-1]+a2[p2++];
}

int init(P E){
	if(E*D[2]>0||D[tot]*E>0) return 0;
	LL ps=lower_bound(D+1,D+tot+1,E,cmp2)-D-1;
	return (E-D[ps])*(D[ps%tot+1]-D[ps])<=0;
} 

int main(){
	scanf("%d%d%d",&n,&m,&Q);
	for(int i=1;i<=n;++i){
		scanf("%lld%lld",&C1[i].x,&C1[i].y);
	}
	for(int i=1;i<=m;++i){
		scanf("%lld%lld",&C2[i].x,&C2[i].y);
		C2[i].x=-C2[i].x;C2[i].y=-C2[i].y;
	}
	Convex(C1,n);
	Convex(C2,m);
	Minkowski();
	Convex(D,tot);
	P O=D[1],E;
	for(int i=1;i<=tot;++i) D[i]=D[i]-O;
	while(Q--){
		scanf("%lld%lld",&E.x,&E.y);
		printf("%d
",init(E-O));
	}
	return 0;
}
原文地址:https://www.cnblogs.com/Yuigahama/p/13822764.html