zoukankan      html  css  js  c++  java
  • #凸包,闵可夫斯基和#CF87E Mogohu-Rea Idol

    题目

    按逆时针顺序给出三个凸包点集 (mathbb{A,B,C}),每次查询给出点 (D)

    问是否存在点 (Ainmathbb{A},Binmathbb{B},Cinmathbb{C}) 满足 (D)(Delta{ABC}) 的重心。


    分析

    考虑重心的坐标就是 ((frac{x_1+x_2+x_3}{3},frac{y_1+y_2+y_3}{3}))

    那么如果将 (D) 的坐标扩大三倍,那么也就是问 (mathbb{A,B,C}) 三个凸包按照坐标分别相加组装成一个新的凸包,点 (D) 是否在这个凸包中。

    可以发现三个凸包可以直接利用闵可夫斯基和合并起来,然后判断点是否位于多边形内部即可


    代码

    #include <cstdio>
    #include <cctype>
    #include <algorithm>
    #define rr register
    using namespace std;
    const int N=150011;
    typedef long long lll; int n,m,_n;
    struct Point{
        lll x,y;
        inline Point operator -(const Point &t)const{
        	return (Point){x-t.x,y-t.y};
    	}
        inline Point operator +(const Point &t)const{
        	return (Point){x+t.x,y+t.y};
    	}
    }a[3][N],_a[N],b[N],B,seg[2][N];
    inline signed iut(){
    	rr int ans=0,f=1; rr char c=getchar();
    	while (!isdigit(c)) f=(c=='-')?-f:f,c=getchar();
    	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
    	return ans*f;
    }
    inline lll Dis(Point x){return x.x*x.x+x.y*x.y;}
    inline lll cj(Point x,Point y){return x.x*y.y-x.y*y.x;}
    inline lll dj(Point x,Point y){return x.x*y.x+x.y*y.y;}
    bool cmp(Point x,Point y){
        rr lll t=cj(x-B,y-B);
        return t>0||(!t&&Dis(x-B)<Dis(y-B));
    }
    inline bool within(Point p){
    	rr Point _p=p-a[2][1];
    	if (cj(_p,_a[2])>0||cj(_p,_a[_n])<0) return 0;
    	rr int l=2,r=_n-1;
    	while (l<=r){
    		rr int mid=(l+r)>>1;
    		if (cj(_p,_a[mid])<=0&&cj(_p,_a[mid+1])>=0)
    			return cj(_a[mid+1]-_p,_a[mid]-_p)<=0;
    		else if (cj(_p,_a[mid])>0) r=mid-1;
    		    else l=mid+1;
    	}
    	return 0;
    }
    inline void Convex(Point *a,int &n){
        rr int o=1,Top;
    	for (rr int i=2;i<=n;++i)
    	if (a[i].x<a[o].x||(a[i].x==a[o].x&&a[i].y<a[o].y)) o=i;
    	swap(a[o],a[1]),B=a[1],sort(a+2,a+1+n,cmp);
    	b[Top=1]=a[1];
    	for (rr int i=2;i<=n;++i){
    		while (Top>1&&cj(a[i]-b[Top-1],b[Top]-b[Top-1])>=0) --Top;
    		b[++Top]=a[i];
        }
        for (rr int i=1;i<=n;++i) a[i]=a[0]; n=Top;
        for (rr int i=1;i<=Top;++i) a[i]=b[i],b[i]=a[0];
    }
    inline void Minkowski(){
    	for (rr int i=1;i<n;++i) seg[0][i]=a[0][i+1]-a[0][i]; seg[0][n]=a[0][1]-a[0][n];
    	for (rr int i=1;i<m;++i) seg[1][i]=a[1][i+1]-a[1][i]; seg[1][m]=a[1][1]-a[1][m];
    	rr int I=1,J=1;
    	a[2][_n=1]=a[0][1]+a[1][1];
    	for (;I<=n&&J<=m;++_n)
    	if (cj(seg[0][I],seg[1][J])>=0) 
    	    a[2][_n+1]=a[2][_n]+seg[0][I++];
    	else a[2][_n+1]=a[2][_n]+seg[1][J++];
    	for (;I<=n;++_n) a[2][_n+1]=a[2][_n]+seg[0][I++];
    	for (;J<=m;++_n) a[2][_n+1]=a[2][_n]+seg[1][J++];
    }
    signed main(){
    	n=iut(); for (rr int i=1;i<=n;++i) a[0][i]=(Point){iut(),iut()};
    	m=iut(); for (rr int i=1;i<=m;++i) a[1][i]=(Point){iut(),iut()};
    	Convex(a[0],n),Convex(a[1],m),Minkowski(),Convex(a[2],_n),n=_n,m=iut();
    	for (rr int i=1;i<=n;++i) a[0][i]=a[2][i];
    	for (rr int i=1;i<=m;++i) a[1][i]=(Point){iut(),iut()};
    	Convex(a[1],m),Minkowski(),Convex(a[2],_n);
    	for (rr int i=2;i<=_n;++i) _a[i]=a[2][i]-a[2][1];
    	for (rr int Q=iut();Q;--Q)
    		puts(within((Point){3*iut(),3*iut()})?"YES":"NO");
    	return 0;
    }
    
  • 相关阅读:
    oracle linux 7.3 dtrace 安装
    ubuntn 内核升级到LINUX v4.11.8:
    ubuntu上安装systemtap
    ubuntu systemtap-sdt-dev
    ubuntu 内核调试符号 网址
    apt-get和apt-cache命令实例展示
    软件包管理 rpm yum apt-get dpkg
    让VIM支持Python2 by update-alternatives
    在Ubuntu中通过update-alternatives切换软件版本
    Ubuntu 11.04安装GCC 4.6.1
  • 原文地址:https://www.cnblogs.com/Spare-No-Effort/p/15521728.html
Copyright © 2011-2022 走看看