• 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;
    }
    
  • 相关阅读:
    Python-装饰器进阶
    JavaScript-CasperJs使用教程
    Python-第三方库requests详解
    PHP-PHP程序员的技术成长规划(By黑夜路人)
    Bootstrap-学习系列
    CSS-常用媒体查询
    Git-随笔
    工具-各种开源
    PHP-PHP5.3及以上版本中检查json格式的方法
    VIM-技巧
  • 原文地址:https://www.cnblogs.com/gary-2005/p/14149565.html
Copyright © 2020-2023  润新知