Live2D

题解 战争

题目传送门

题目大意

给出两个凸包\(A,B\),对于一个向量求出是否能通过按此向量移动其中一个凸包使得两个凸包没有交集。

凸包大小、查询次数\(\le 10^5\)

思路

其实是个闵可夫斯基和的板题。

我们发现如果对于该向量\(\vec{x}\),存在\(a\in A,b\in B\)满足\(a+\vec{x}=b\)那么,显然两个凸包就会有交集。于是,判断一个向量\(\vec{x}\)是否合法的方法就出来了,我们可以判断是否存在\(a\in A,b\in B\)使得\(\vec{x}=a-b\)。然后我们发现如果我们设\(C\)\(A,(-B)\)的闵可夫斯基和的凸包,那么,答案就是\(\vec{x}\)是否在\(C\)中。

至于如何求出闵可夫斯基和以及如何判断一个向量是否在一个凸包之中,可以看看xzyxzy的博客

\(\texttt{Code}\)

#include <bits/stdc++.h>
using namespace std;

#define Int register int
#define int long long
#define MAXN 100005

template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}while (c >= '0' && c <= '9'){t = (t << 3) + (t << 1) + c - '0';c = getchar();} t *= f;}
template <typename T,typename ... Args> inline void read (T &t,Args&... args){read (t);read (args...);}
template <typename T> inline void write (T x){if (x < 0){x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0');}

struct Vector{
	int x,y;
	int len (){return x * x + y * y;}
	int operator * (const Vector &p)const{return x * p.y - y * p.x;}
	Vector operator + (const Vector &p)const{return Vector {x + p.x,y + p.y};}
	Vector operator - (const Vector &p)const{return Vector {x - p.x,y - p.y};}
};

bool cmp1 (Vector a,Vector b){return a.y < b.y || (a.y == b.y && a.x < b.x);}
bool cmp2 (Vector a,Vector b){return a * b > 0 || (a * b == 0 && a.len () < b.len());}

int tot,top,sta[MAXN];

void Convex (Vector *A,int &n){
	sort (A + 1,A + n + 1,cmp1);
	Vector st = A[1];for (Int i = 1;i <= n;++ i) A[i] = A[i] - st;
	sort (A + 2,A + n + 1,cmp2),sta[top = 1] = 1;
	for (Int i = 2;i <= n;sta[++ top] = i,++ i) while (top > 1 && (A[i] - A[sta[top - 1]]) * (A[sta[top]] - A[sta[top - 1]]) >= 0) -- top;
	for (Int i = 1;i <= top;++ i) A[i] = A[sta[i]] + st;
	n = top,A[n + 1] = A[1];
}

int n,m,q;
Vector s1[MAXN],s2[MAXN],A[MAXN],C1[MAXN],C2[MAXN];

void Minkowski (){
	for (Int i = 1;i < n;++ i) s1[i] = C1[i + 1] - C1[i];s1[n] = C1[1] - C1[n];
	for (Int i = 1;i < m;++ i) s2[i] = C2[i + 1] - C2[i];s2[m] = C2[1] - C2[m];
	A[tot = 1] = C1[1] + C2[1];int st1 = 1,st2 = 1;
	while (st1 <= n && st2 <= m) ++ tot,A[tot] = A[tot - 1] + (s1[st1] * s2[st2] >= 0 ? s1[st1 ++] : s2[st2 ++]);
	while (st1 <= n) ++ tot,A[tot] = A[tot - 1] + s1[st1 ++];
	while (st2 <= m) ++ tot,A[tot] = A[tot - 1] + s2[st2 ++];
}

bool Inside (Vector a){
	if (a * A[1] > 0 || A[tot] * a > 0) return 0;
	int pos = lower_bound (A + 1,A + tot + 1,a,cmp2) - A - 1;
	return (a - A[pos]) * (A[pos % tot + 1] - A[pos]) <= 0;
}

signed main(){
	read (n,m,q);
	for (Int i = 1;i <= n;++ i) read (C1[i].x,C1[i].y);Convex (C1,n);
	for (Int i = 1;i <= m;++ i) read (C2[i].x,C2[i].y),C2[i].x = -C2[i].x,C2[i].y = -C2[i].y;Convex (C2,m);
	Minkowski (),Convex (A,tot);Vector st = A[1];for (Int i = 1;i <= tot;++ i) A[i] = A[i] - st;
	for (Int i = 1;i <= q;++ i){
		Vector que;read (que.x,que.y);
		write (Inside (que - st)),putchar ('\n');
	}
	return 0;
}
posted @ 2020-07-23 17:55  Dark_Romance  阅读(116)  评论(0编辑  收藏  举报