• 【计算几何】【凸包】【极角排序】【二分】Gym


    平面上n个红点,m个黑点,问你多少个黑点至少在一个红三角形内。

    对红点求凸包后,转化为询问有多少个黑点在凸包内。

    点在凸多边形内部判定,选定一个凸包上的点作原点,对凸包三角剖分,将其他的点极角排序之后,使用二分法就可以判定点在哪个剖分出来的三角形的夹角内,然后用叉积即可判定其在凸包内还是外,O(logn):

    http://www.cnblogs.com/dream-wind/archive/2012/05/23/2514694.html

    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    typedef long long ll;
    int n,m,K,O;
    struct Point{
    	ll x,y;
    	double jiao;
    	Point(){}
    	Point(const ll &x,const ll &y){
    		this->x=x;
    		this->y=y;
    	}
    	void Read(){
    		scanf("%lld%lld",&x,&y);
    	}
    };
    typedef Point Vector;
    Point p0,p;
    Vector operator - (const Point &a,const Point &b){
    	return Vector(a.x-b.x,a.y-b.y);
    }
    ll Cross(const Vector &a,const Vector &b){
    	return a.x*b.y-a.y*b.x;
    }
    bool cmp(const Point &a,const Point &b){
    	return a.x!=b.x ? a.x<b.x : a.y<b.y;
    }
    bool cm2(const Point &a,const Point &b){
    	return a.jiao<b.jiao;
    }
    Point ps[10010],qs[10010];
    bool check(int mid){
    	return Cross(qs[mid]-p0,p-p0)<=0;
    }
    int main(){
    //	freopen("j.in","r",stdin);
    	scanf("%d",&n);
    	for(int i=0;i<n;++i){
    		ps[i].Read();
    	}
    	sort(ps,ps+n,cmp);
    	for(int i=0;i<n;++i){
    		while(K>1 && Cross(qs[K-1]-qs[K-2],ps[i]-qs[K-1])<=0){
    			--K;
    		}
    		qs[K++]=ps[i];
    	}
    	for(int i=n-2,t=K;i>=0;--i){
    		while(K>t && Cross(qs[K-1]-qs[K-2],ps[i]-qs[K-1])<=0){
    			--K;
    		}
    		qs[K++]=ps[i];
    	}
    	--K;
    	for(int i=1;i<K;++i){
    		if(qs[i].y<qs[O].y || (qs[i].y==qs[O].y && qs[i].x<qs[O].x)){
    			O=i;
    		}
    	}
    	p0=qs[O];
    	for(int i=0;i<K;++i){
    		qs[i].jiao=atan2((double)(qs[i].y-qs[O].y),(double)(qs[i].x-qs[O].x));
    	}
    	for(int i=O;i<K-1;++i){
    		qs[i]=qs[i+1];
    	}
    	--K;
    	sort(qs,qs+K,cm2);
    	scanf("%d",&m);
    	int ans=0;
    	for(int i=1;i<=m;++i){
    		p.Read();
    		if(Cross(p-p0,qs[0]-p0)<=0 && Cross(p-p0,qs[K-1]-p0)>=0){
    			int l=1,r=K-1;
    			while(l<r){
    				int mid=(l+r>>1);
    				if(check(mid)){
    					r=mid;
    				}
    				else{
    					l=mid+1;
    				}
    			}
    			if(Cross(p-qs[l-1],qs[l]-qs[l-1])<=0){
    				++ans;
    			}
    		}
    	}
    	printf("%d
    ",ans);
    	return 0;
    }
  • 相关阅读:
    MagicAjax.NET Framework
    实例说明sql优化的重要性
    求助:谁可以给我点share point 开发的资料
    整理了一些tsql技巧(收藏)
    熟悉/了解C#基础问题
    .NET在SQL Server中的图片存取技术(例子在管理里InOutImg)
    SQL Server 2000 函数使用CAST 和 CONVERT
    MagicAjax.NET Framework configuration
    找工作了,希望各位多多帮忙
    OSG节点访问和遍历
  • 原文地址:https://www.cnblogs.com/autsky-jadek/p/7296653.html
Copyright © 2020-2023  润新知