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;
}