Saint John Festival Gym - 101128J (凸包二分)
Problem J: Saint John Festival
\]
题意
给出\(n\)个大点,和\(m\)个小点,然后问有多少个小点可以在任意一个\(3\)个大点组成的三角形内。
思路
很明显只要对大点求凸包,然后判断有多少个在凸包里的小点就可以了,但是判断点在凸包内如果用\(O(N)\)的方法会\(TLE\),需要进行二分。
我求出的是逆时针的凸包,然后定下一个端点\(p[1]\),寻找另外两个端点\(p[id]\)和\(p[id+1]\),根据查询的点在\(p[1]-p[id]\)这条直线右侧或者在\(p[1]-p[id+1]\)这个点左侧来二分范围,如果在\(p[1]-p[id]\)和\(p[1]-p[id+1]\)之间,那么在判断是否在\(p[id]-p[id+1]\)左侧来判断是否在凸包内。
/***************************************************************
    > File Name    : J.cpp
    > Author       : Jiaaaaaaaqi
    > Created Time : 2019年05月06日 星期一 18时14分21秒
 ***************************************************************/
#include <map>
#include <set>
#include <list>
#include <ctime>
#include <cmath>
#include <stack>
#include <queue>
#include <cfloat>
#include <string>
#include <vector>
#include <cstdio>
#include <bitset>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define  lowbit(x)  x & (-x)
#define  mes(a, b)  memset(a, b, sizeof a)
#define  fi         first
#define  se         second
#define  pii        pair<int, int>
#define  INOPEN     freopen("in.txt", "r", stdin)
#define  OUTOPEN    freopen("out.txt", "w", stdout)
typedef unsigned long long int ull;
typedef long long int ll;
const int    maxn = 5e4 + 10;
const int    maxm = 1e5 + 10;
const ll     mod  = 1e9 + 7;
const ll     INF  = 1e18 + 100;
const int    inf  = 0x3f3f3f3f;
const double pi   = acos(-1.0);
const double eps  = 1e-8;
using namespace std;
int n, m;
int cas, tol, T;
int sgn(double x) {
	if(fabs(x) <= eps)	return 0;
	else	return x>0 ? 1 : -1;
}
struct Point {
	double x, y;
	Point() {}
	inline Point(double _x, double _y) {
		x = _x, y = _y;
	}
	inline Point operator - (Point a) const {
		return Point(x-a.x, y-a.y);
	}
	inline double operator ^ (Point a) const {
		return x*a.y - y*a.x;
	}
	inline double distance(Point p) const {
		return hypot(x-p.x, y-p.y);
	}
	inline bool operator < (Point a) const {
		return sgn(y-a.y)==0 ? sgn(x-a.x)<0 : y<a.y;
	}
	inline bool operator == (Point a) const {
		return sgn(x-a.x)==0 && sgn(y-a.y)==0;
	}
	inline double operator * (Point a) const {
		return x*a.x + y*a.y;
	}
};
struct Line {
	Point s, e;
	Line() {}
	Line(Point _s, Point _e) {
		s = _s, e = _e;
	}
	inline bool pointseg(Point p) {
		return sgn((p-s)^(e-s)) == 0 && sgn((p-s)*(p-e)) <=0;
	}
};
struct Polygon {
	int n;
	Point p[maxn];
	Line l[maxn];
	inline void add(Point q) {
		p[++n] = q;
	}
	struct cmp {
		Point p;
		cmp(Point _p) {
			p = _p;
		}
		bool operator() (Point _a, Point _b) const {
			Point a = _a, b = _b;
			int d = sgn((a-p)^(b-p));
			if(d == 0) {
				return sgn(a.distance(p) - b.distance(p)) < 0;
			} else {
				return d>0;
			}
		}
	};
	void norm() {
		int id = 1;
		for(int i=2; i<=n; ++i) {
			if(p[i] < p[id])
				id = i;
		}
		swap(p[id], p[1]);
		sort(p+1, p+1+n, cmp(p[1]));
	}
	void Graham(Polygon &convex) {
		norm();
		mes(convex.p, 0);
		int &top = convex.n = 0;
		if(n == 1) {
			convex.p[++top] = p[1];
		} else if(n == 2) {
			convex.p[++top] = p[1];
			convex.p[++top] = p[2];
			if(convex.p[1] == convex.p[2])	top--;
		} else {
			convex.p[++top] = p[1];
			convex.p[++top] = p[2];
			for(int i=3; i<=n; ++i) {
				while(top>1 && sgn((convex.p[top]-convex.p[top-1])^
					(p[i]-convex.p[top-1])) <= 0)
						top--;
				convex.p[++top] = p[i];
			}
			if(top == 2 && convex.p[1] == convex.p[2])
				top--;
		}
	}
	void getline() {
		for(int i=1; i<=n; ++i) {
			l[i] = Line(p[i], p[i%n+1]);
		}
	}
	int inconvex(Point s) {
		/*
		点和凸包的关系
		2	边上
		1	内部
		0	外部
		*/
		Point p1 = p[1];
		Line l1 = Line(p[1], p[2]);
		Line l2 = Line(p[1], p[n]);
		if(l1.pointseg(s) || l2.pointseg(s))
			return 2;
		int l = 2, r = n-1;
		while(l<=r) {
			int mid = l+r>>1;
			int t1 = sgn((s-p1)^(p[mid]-p1));
			int t2 = sgn((s-p1)^(p[mid+1]-p1));
			if(t1 <= 0 && t2 >= 0) {
				int t3 = sgn((s-p[mid]) ^ (p[mid+1]-p[mid]));
				if(t3 < 0)	return 1;
				else if(t3 == 0)	return 2;
				return 0;
			}
			if(t1 > 0)	r = mid-1;
			else	l = mid+1;
		}
		return 0;
	}
} large, small, con;
inline int read() {
	int x = 0, f = 1;
	char s = getchar();
	while (s < '0' || s > '9') {
		if (s == '-')f = -1;
		s = getchar();
	}
	while (s >= '0' && s <= '9') {
		x = x * 10 + s - '0';
		s = getchar();
	}
	return x * f;
}
int main() {
	n = read();
	large.n = small.n = con.n = 0;
	int x, y;
	for(int i=1; i<=n; ++i) {
		x = read(), y =read();
		large.add(Point(1.0*x, 1.0*y));
	}
	m = read();
	for(int i=1; i<=m; ++i) {
		x = read(), y =read();
		small.add(Point(1.0*x, 1.0*y));
	}
	large.norm();
	large.Graham(con);
	int ans = 0;
	for(int i=1; i<=m; ++i) {
		if(con.inconvex(small.p[i])) {
			ans++;
		}
	}
	printf("%d\n", ans);
	return 0;
}
Saint John Festival Gym - 101128J (凸包二分)的更多相关文章
- UVALive 7281	Saint John Festival (凸包+O(logn)判断点在凸多边形内)
		Saint John Festival 题目链接: http://acm.hust.edu.cn/vjudge/contest/127406#problem/J Description Porto's ... 
- Gym 101128J Saint John Festival(凸包 + 二分判点和凸包关系)题解
		题意:给你一堆黑点一堆红点,问你有最多几个黑点能找到三个红点,使这个黑点在三角形内? 思路:显然红点组成的凸包内的所有黑点都能做到.但是判断黑点和凸包的关系朴素方法使O(n^2),显然超时.那么我现在 ... 
- 【计算几何】【凸包】【极角排序】【二分】Gym - 101128J - Saint John Festival
		平面上n个红点,m个黑点,问你多少个黑点至少在一个红三角形内. 对红点求凸包后,转化为询问有多少个黑点在凸包内. 点在凸多边形内部判定,选定一个凸包上的点作原点,对凸包三角剖分,将其他的点极角排序之后 ... 
- UVA 13024: Saint John Festival(凸包+二分 ,判定多个点在凸包内)
		题意:给定N个点,Q次询问,问当前点知否在N个点组成的凸包内. 思路:由于是凸包,我们可以利用二分求解. 二分思路1:求得上凸包和下凸包,那么两次二分,如果点在对应上凸包的下面,对应下凸包的上面,那么 ... 
- UVA - 13024 Saint John Festival 凸包+二分
		题目链接:https://vjudge.net/problem/UVA-13024 题意:先给出\(L\)个点构造一个凸包,再给出\(S\)个点,询问有几个点在凸包内. 题解:判断点是否在凸包内的模板 ... 
- 15-16 ICPC europe J Saint John Festival (graham扫描法+旋转卡壳)
		题意:给n个大点,m个小点$(n<=1e5,m<=5e5),问有多少个小点,存在3个大点,使小点在三个大点组成的三角形内. 解题思路: 首先,易证,若该小点在某三大点行成的三角形内,则该小 ... 
- 【bzoj3203】[Sdoi2013]保护出题人  凸包+二分
		题目描述 输入 第一行两个空格隔开的正整数n和d,分别表示关数和相邻僵尸间的距离.接下来n行每行两个空格隔开的正整数,第i + 1行为Ai和 Xi,分别表示相比上一关在僵尸队列排头增加血量为Ai 点的 ... 
- 【bzoj2402】陶陶的难题II  分数规划+树链剖分+线段树+STL-vector+凸包+二分
		题目描述 输入 第一行包含一个正整数N,表示树中结点的个数.第二行包含N个正实数,第i个数表示xi (1<=xi<=10^5).第三行包含N个正实数,第i个数表示yi (1<=yi& ... 
- UOJ#7 NOI2014 购票 点分治+凸包二分 斜率优化DP
		[NOI2014]购票 链接:http://uoj.ac/problem/7 因为太麻烦了,而且暴露了我很多学习不扎实的问题,所以记录一下具体做法. 主要算法:点分治+凸包优化斜率DP. 因为$q_i ... 
随机推荐
- 重点|183道Java面试题可以说很详细了
			<p style="text-align: right;"><span style="font-size: 14px;color: rgb(136, 1 ... 
- java中反射知识点总结
			1 package Demo; 2 3 import java.lang.reflect.Constructor; 4 import java.lang.reflect.Field; 5 impo ... 
- ASP.NET Core 静态文件
			静态文件(HTML,CSS,图片和Javascript之类的资源)会被ASP.NET Core应用直接提供给客户端. 静态文件通常位于网站根目录(web root) <content-root& ... 
- OpenFire后台插件上传获取webshell及免密码登录linux服务器
			1.目标获取 (1)fofa.so网站使用搜索body="Openfire, 版本: " && country=JP,可以获取日本存在的Openfire服务器.如图 ... 
- APS应用案例|纽威阀门实现高效排产
			企业背景: 苏州纽威阀门股份有限公司(下文简称:纽威阀门)成立于1997年,总部设在江苏苏州.自成立以来一直致力于工业阀门的研发与制造,以为客户提供全套工业阀门解决方案为目标.纽威阀门通过企业的努力发 ... 
- Java集合学习(6):LinkedHashSet
			一.概述 首先我们需要知道的是它是一个Set的实现,所以它其中存的肯定不是键值对,而是值.此实现与HashSet的不同之处在于,LinkedHashSet维护着一个运行于所有条目的双重链接列表.此链接 ... 
- Linux 常用命令(根据自己的理解随时更新)
			1. linux 目录解释系统启动必须: /boot:存放的启动 Linux 时使用的内核文件,包括连接文件以及镜像文件. /etc:存放所有的系统需要的配置文件和子目录列表,更改目录下的文件可能会导 ... 
- Linux之ubuntu下载
			(转载) ubuntu 16.04国内下载地址: 中科大源 http://mirrors.ustc.edu.cn/ubuntu-releases/16.04/ 阿里云开源镜像站 http://mirr ... 
- (一)MongoDB安装
			(一)MongoDB安装 mongodb 2018年03月06日 15时53分29秒 安装准备 启动mongodb 1.命令行参数启动 2.从配置文件启动 使用服务启动mongodb 参数解释 用户授 ... 
- mysql查询语句中使用星号真的慢的要死?
			前言 之所以写这篇文章,是源于以前看过的关于sql语句优化的帖子,里面明确提到了在sql语句中不要使用 * 来做查询,就像下面的规则中说的 2.尽量避免使用select *,返回无用的字段会降低查询效 ... 
