JSOI 2018 战争题解

JSOI2018 战争 题解

题目传送门

假设A部落占领的点集为(A),B部落的为(B)

则问题转换成,给你一个向量(v)。判断是否(exists ain A,b+v=a,(bin B))

则是否存在(a-b=v)

若我们可以处理出(a-b)的点集(C)。问题就转换成查询一个向量是否在一个凸包内。

我们将所有(B)中的点乘上(-1)。得到(B')

然后处理出向量(A)(B)的闵科夫斯基和。关于闵科夫斯基和

可以得到一个大凸包。

然后取最下面的点(如果右多个就取最左面的)作为极点。将其它点极交排序。然后就可以用二分找到所属于的三角形假设是( riangle ABO)(O)为极点。只需要判断({underset{A-v}{ ightarrow}}和 underset{B-v}{ ightarrow})叉乘的结果 的正负就好了。

注意:闵科夫斯基和一定要去除共线的点。

/*
{
######################
#       Author       #
#        Gary        #
#        2020        #
######################
*/
#include<bits/stdc++.h>
#define rb(a,b,c) for(int a=b;a<=c;++a)
#define rl(a,b,c) for(int a=b;a>=c;--a)
#define LL long long
#define IT iterator
#define PB push_back
#define II(a,b) make_pair(a,b)
#define FIR first
#define SEC second
#define FREO freopen("check.out","w",stdout)
#define rep(a,b) for(int a=0;a<b;++a)
#define SRAND mt19937 rng(chrono::steady_clock::now().time_since_epoch().count())
#define random(a) rng()%a
#define ALL(a) a.begin(),a.end()
#define POB pop_back
#define ff fflush(stdout)
#define fastio ios::sync_with_stdio(false)
#define check_min(a,b) a=min(a,b)
#define check_max(a,b) a=max(a,b)
using namespace std;
//inline int read(){
//    int x=0;
//    char ch=getchar();
//    while(ch<'0'||ch>'9'){
//        ch=getchar();
//    }
//    while(ch>='0'&&ch<='9'){
//        x=(x<<1)+(x<<3)+(ch^48);
//        ch=getchar();
//    }
//    return x;
//}
const double INF=1e18;
typedef pair<int,int> mp;
/*}
*/
const double pi=3.1415926535897932384626433832795;
const double eps=1e-10;
struct vec{
	double x,y;
	vec(){}
	vec(double X,double Y){
		x=X;
		y=Y;
	}
	bool operator < (vec oth){
		if(x!=oth.x) return x<oth.x;
		return y<oth.y;
	}
	double operator * (vec oth){
		return x*oth.y-oth.x*y;
	}
	vec operator - (vec oth){
		return vec(x-oth.x,y-oth.y);
	}
	vec operator + (vec oth){
		return vec(x+oth.x,y+oth.y);
	}
	bool operator != (vec oth){
		return (abs(x-oth.x)>eps)||(abs(y-oth.y)>eps);
	}
};
double angle(vec v){
	if(v.y>=0){
		if(abs(v.x)<=eps) return pi/2.0;
		if(v.x>eps){
			return atan(v.y/v.x);
		}
		else return atan(v.y/v.x)+pi;
	}
	if(abs(v.x)<=eps) return pi/2.0+pi;
	if(v.x>eps){
		 return atan(v.y/v.x)+2.0*pi;
	}
	return atan(v.y/v.x)+pi;
}
bool cmp(vec A,vec B){
	return angle(A)<angle(B);
}
vector<int> sta;
bool used[200000+20];
struct convex_hull{
	vector<vec> v;
	convex_hull(){}
	convex_hull(vector<vec> points){
		memset(used,0,sizeof(used));
		sta.clear();
		sta.PB(0);
		sort(ALL(points));
		rep(i,points.size()){
			if(!i) continue;
			while(sta.size()>1&&(points[sta.back()]-points[sta[sta.size()-2]])*(points[i]-points[sta.back()])<=0){
				used[sta.back()]=0;
				sta.POB();
			}
			used[i]=1;
			sta.PB(i);
		}
		int tmp=sta.size();
		rl(i,points.size()-1,0){
			if(used[i]) continue;
			while(sta.size()>tmp&&(points[sta.back()]-points[sta[sta.size()-2]])*(points[i]-points[sta.back()])<=0)  sta.POB();
			sta.PB(i);
		}
		for(auto it:sta) v.PB(points[it]);
		v.POB();
	}
	convex_hull operator + (convex_hull oth){
		vec ma=vec(INF,INF),mb=vec(INF,INF);
		for(auto it:v){
			if(it.y<ma.y){
				ma=it;
			}
			else if(it.y==ma.y&&it.x<ma.x) ma=it;
		}
		for(auto it:oth.v){
			if(it.y<mb.y){
				mb=it;
			}
			else if(it.y==mb.y&&it.x<mb.x) mb=it;
		}
		ma=ma+mb;
		vector<vec> nv;
		rep(i,v.size()){
			nv.PB(v[(i+1)%v.size()]-v[i]);
		}
		rep(i,oth.v.size()){
			nv.PB(oth.v[(i+1)%oth.v.size()]-oth.v[i]);
		}
		sort(ALL(nv),cmp);
		convex_hull ret;
		vec now=vec(0,0);
		for(auto it:nv){
			ret.v.PB(now);	
			now=now+it;
		}
		for(auto & it:ret.v) it=it+ma;
		return ret;
	}
	vec get_polar_point(){
		vec ret=vec(INF,INF);
		for(auto it:v){
			if(it.y<ret.y) ret=it;
			else if(it.y==ret.y&&it.x<ret.x) ret=it;
		}
		return ret;
	}
};
int main(){
	int n,m,q;
	scanf("%d%d%d",&n,&m,&q);
	vector<vec> points;
	rb(i,1,n){
		int x,y;
		scanf("%d%d",&x,&y);
		points.PB(vec(x,y));
	}
	convex_hull A(points);
	points.clear();
	rb(i,1,m){
		int x,y;
		scanf("%d%d",&x,&y);
		x=-x;
		y=-y;
		points.PB(vec(x,y));
	}
	convex_hull B(points);
	A=A+B;
	A=convex_hull(A.v);
	vec pp=A.get_polar_point();	
	for(auto &it:A.v){
		it=it-pp;
	}
	vector<vec> oth;
	for(auto it:A.v){
		if(it!=vec(0,0)){
			oth.PB(it);
		}
	}
	sort(ALL(oth),cmp);
	rb(i,1,q){
		int x,y;
		scanf("%d%d",&x,&y);
		vec query=vec(x,y);
		query=query-pp;
		bool ok=false;
		int is=upper_bound(ALL(oth),query,cmp)-oth.begin();
		if(is==oth.size()){
			if(abs(angle(oth.back())-angle(query))<=eps&&oth.back().x+eps>=query.x){
				ok=true;
			}
		}
		else{
			if(is!=0){
				vec u,d;
				u=oth[is];
				d=oth[is-1];
				if((u-query)*(d-query)<=eps){
					ok=true;
				}
			}
			else{
				if(abs(angle(oth[0])-angle(query))<=eps&&oth[0].x+eps>=query.x){
					ok=true;
				}
			}
		}
		printf("%d
",ok);
	}
	return 0;
}
原文地址:https://www.cnblogs.com/gary-2005/p/14149565.html