zoukankan      html  css  js  c++  java
  • SGU 253. Theodore Roosevelt 极角序+二分

    /*
    * 253. Theodore Roosevelt
    * 题目:给出一个逆时针的凸包,然后再给出m个点,问这m个点是否至少有k个点在凸包里面
    * (包括在边界上)
    * 分析:O(n)的询问方式肯定TLE,所以我们可以像做动态凸包那种方式用set或者splay来维
    * 护一个极角序,二分询问的那个点的极角,然后再用叉积判断即可。

    我们可以时刻用极角序维护一个凸包的点集。我们插入点pos的时候,我们可以计算出pos的极角,然后二分出pos的位置

    (pos的极角恰好为p[i],p[i+1]中间)。然后判断叉积det(pos,p[i+1],p[i])是否新插入的点在凸包中。


    *
    * */

    #include <cstdio>
    #include <cstring>
    #include <set>
    #include <cmath>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    typedef long long ll;
    
    const double eps = 1e-8;
    const int X = 100005;
    
    int dcmp(double x){
    	if(fabs(x)<eps)
    		return 0;
    	return x>0?1:-1;
    }
    
    struct Point{
    	ll x,y;
    	double angle;
    	Point(){}
    	Point(ll _x,ll _y):x(_x),y(_y){}
    	friend bool operator < (Point a,Point b){
    		return dcmp(a.angle-b.angle)<0;
    	}
    	friend Point operator - (Point a,Point b){
    		return Point(a.x-b.x,a.y-b.y);
    	}
    	void input(){
    		scanf("%lld%lld",&x,&y);
    		angle = atan2(y,x);
    	}
    };
    
    set<Point> Convex;
    int n,m,k;
    
    ll det(Point a,Point b){
    	return a.x*b.y-a.y*b.x;
    }
    
    ll det(Point a,Point b,Point o){
    	return det(a-o , b-o);
    }
    
    Point Pre(Point pos){
    	set<Point>::iterator it = Convex.lower_bound(pos);
    	if(it==Convex.begin())
    		return *(--Convex.end());
    	return *(--it);
    }
    
    Point Next(Point pos){
    	set<Point>::iterator it = Convex.upper_bound(pos);
    	if(it==Convex.end())
    		return *Convex.begin();
    	return *it;
    }
    
    int cal(Point pos){
    	Point pre = Pre(pos);
    	Point next = Next(pre);
    	return det(pre,next,pos)>=0;
    }
    
    int main(){
    	//freopen("sumd.txt","r",stdin);
    	cin>>n>>m>>k;
    	Convex.clear();
    	Point pos;
    	for(int i=0;i<n;i++){
    		pos.input();
    		Convex.insert(pos);
    	}
    	int ans = 0;
    	while(m--){
    		pos.input();
    		ans += cal(pos);
    		if(ans>=k)
    			break;
    	}
    	ans>=k?puts("YES"):puts("NO");
    
    	return 0;
    }
    

      

  • 相关阅读:
    [Java]用于将链表变成字符串并在元素之间插入分隔符的有用函数“String.join”
    Sql语法树示例 select username, ismale from userinfo where age > 20 and level > 5 and 1 = 1
    [Java]一段尚未雕琢的分词代码
    day44_Oracle学习笔记_03
    day43_Oracle学习笔记_02
    WinXP系统中的Oracle数据库如何以管理员身份登录
    Oracle 10G安装指导
    20个Linux服务器性能调优技巧
    Linux 上使用 Gmail SMTP 服务器发送邮件通知
    Netdata Linux下性能实时监测工具
  • 原文地址:https://www.cnblogs.com/yejinru/p/2855716.html
Copyright © 2011-2022 走看看