P4557 [JSOI2018]战争 题解

Luogu

Description.

有两个部落,每个部落有一些营地,对应为二维平面上的一些点。
定义两个部落会发生重读,当且仅当满足以下条件之一。
定义一个部落的控制范围是它所有营地构成的凸包。
定义两个部落会发生冲突,当且仅当一个部落的一个营地在另一个部落控制范围内。
现在,向往核平的第二个部落首领决定搬迁避免战争,具体的,他会确定一个向量,所有营地平移这个向量。
他给出了 \(Q\) 个方案,他想问你每个方案能否成功避免战争。

Solution.

首先,我们考虑这个平移,会让我们想到闵可夫斯基和。
但是闵可夫斯基和是两个凸包之间的关系。
我们考虑 \(B+\vec p=B'\Leftrightarrow A\),是不是可以直接认为 \(\vec p\Leftrightarrow A-B\)
然后我们设 \(-B\) 等于 \(B\) 坐标取反后得到的凸包。
然后判断 \(\vec p\) 是否在 \(A+(-B)\) 内即可。

Coding.

点击查看弱小代码
//是啊,你就是那只鬼了,所以被你碰到以后,就轮到我变成鬼了{{{
#include<bits/stdc++.h>
using namespace std;typedef long long ll;
template<typename T>inline void read(T &x)
{
	x=0;char c=getchar(),bz=0;
	for(;c<48||c>57;c=getchar()) if(!(c^45)) bz=1;
	for(;c>=48&&c<=57;c=getchar()) x=(x<<1)+(x<<3)+(c^48);
	bz?x=-x:x;
}/*}}}*/
int n,m,Q,tt,CX[200005];
struct Vec
{
	ll x,y;
	inline Vec operator+(Vec b) const {return(Vec){x+b.x,y+b.y};}
	inline Vec operator-(Vec b) const {return(Vec){x-b.x,y-b.y};}
	inline ll operator^(Vec b) const {return x*b.x+y*b.y;}
	inline ll operator*(Vec b) const {return x*b.y-y*b.x;}
	inline ll dis() {return x*x+y*y;}
}a[200005],b[200005],r[200005],v1[200005],v2[200005];
inline char cmp(Vec a,Vec b) {return a*b>0||(a*b==0&&a.dis()<b.dis());}
inline void convex(int &n,Vec *a)
{
	int tp=0;sort(a+1,a+n+1,[](Vec a,Vec b){return fabs(a.y-b.y)<1e-8?a.x<b.x:a.y<b.y;});
	Vec bas=a[1];CX[tp=1]=1;for(int i=1;i<=n;i++) a[i]=a[i]-bas;
	sort(a+2,a+n+1,cmp);for(int i=2;i<=n;CX[++tp]=i++)
		while(tp>1&&(a[i]-a[CX[tp-1]])*(a[CX[tp]]-a[CX[tp-1]])>=0) tp--;
	for(int i=1;i<=tp;i++) a[i]=a[CX[i]]+bas;
	n=tp,a[n+1]=a[1];
}
inline void solve()
{
	v1[n]=a[1]-a[n];for(int i=1;i<n;i++) v1[i]=a[i+1]-a[i];
	v2[m]=b[1]-b[m];for(int i=1;i<m;i++) v2[i]=b[i+1]-b[i];
	int w1=1,w2=1;r[tt=1]=a[1]+b[1];
	while(w1<=n&&w2<=m) ++tt,r[tt]=r[tt-1]+(v1[w1]*v2[w2]>=0?v1[w1++]:v2[w2++]);
	while(w1<=n) ++tt,r[tt]=r[tt-1]+v1[w1++];
	while(w2<=m) ++tt,r[tt]=r[tt-1]+v2[w2++];
}
inline char chk(Vec a)
{
	if(a*r[1]>0||r[tt]*a>0) return 0;
	int wh=lower_bound(r+1,r+tt+1,a,cmp)-r-1;
	return (a-r[wh])*(r[wh%tt+1]-r[wh])<=0;
}
int main()
{
	read(n),read(m),read(Q);Vec base,in;
	for(int i=1;i<=n;i++) read(a[i].x),read(a[i].y);
	for(int i=1;i<=m;i++) read(b[i].x),read(b[i].y),b[i].x=-b[i].x,b[i].y=-b[i].y;
	convex(n,a),convex(m,b),solve(),convex(tt,r);
	base=r[1];for(int i=tt;i>=1;i--) r[i]=r[i]-r[1];
	while(Q--) read(in.x),read(in.y),printf("%d\n",chk(in-base));
	return 0;
}
posted @ 2021-08-16 22:11  Peal_Frog  阅读(86)  评论(0编辑  收藏  举报