ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

题解 战争

2020-07-23 18:03:09  阅读:218  来源: 互联网

标签:战争 return int 题解 凸包 Vector vec const


题目传送门

题目大意

给出两个凸包\(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;
}

标签:战争,return,int,题解,凸包,Vector,vec,const
来源: https://www.cnblogs.com/Dark-Romance/p/13367752.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有