HHHOJ #151. 「NOI模拟 #2」Nagisa
计算几何板子题(我才没有拷板子的说……)
众所周知,三角形的重心坐标是\((\frac{x_1+x_2+x_3}{3},\frac{y_1+y_2+y_3}{3})\)
然后我们发现如果我们有一个点集\(P=\{\vec a+\vec b+\vec c|\vec a\in A,\vec b \in B,\vec c\in C\}\),那么就可以直接查询\((3\times x_,3\times y)\)在不在这个点集里得到答案
其实这样的点集在计算几何上是有名字的,就是传说中的闵可夫斯基和
通俗地讲,点集\(A,B\)的闵可夫斯基和就是:从原点向\(A\)内部的每一个点做向量,将\(B\)沿每个向量移动,所有的最终位置的并
然后我们考虑凸包的闵可夫斯基和,手玩一下就会发现它的边是由原来凸包的边构成的
也就是说把两凸包的边极角排序后直接顺次连起来就是闵可夫斯基和,那么我们求的时候直接归并排序即可(凸包已经有序了)
所以这题就做完了,点在凸包内可以直接搞一个点作为原点,然后二分找极角最接近的边判断
坑点1:可能出现三点共线的情况,因此要扔回去再求一遍凸包
坑点2:极角排序的时候注意三点共线
坑点3:如果找到的极角最接近的边已经到最大的一条了,那么请考虑共线的情况
CODE
#include<cstdio>
#include<algorithm>
#define RI register LL
#define CI const LL&
using namespace std;
typedef long long LL;
const LL N=1000005;
struct Point
{
LL x,y;
inline Point(LL X=0,LL Y=0)
{
x=X; y=Y;
}
inline friend bool operator ==(const Point& A,const Point& B)
{
return A.x==B.x&&A.y==B.y;
}
}A[N],B[N],C[N],stack[N*3],t[N*3],p,st; LL n,m,k,q,num;
typedef Point Vector;
inline LL Cross(const Vector& A,const Vector& B)
{
return A.x*B.y-A.y*B.x;
}
inline LL Dot(const Vector& A,const Vector& B)
{
return A.x*B.x+A.y*B.y;
}
inline Point operator +(const Point& A,const Point& B)
{
return Point(A.x+B.x,A.y+B.y);
}
inline Vector operator -(const Point& A,const Point& B)
{
return Vector(A.x-B.x,A.y-B.y);
}
inline Point operator *(const Point& A,CI v)
{
return Point(A.x*v,A.y*v);
}
inline bool cmp(const Point& A,const Point& B)
{
return A.x<B.x||(A.x==B.x&&A.y<B.y);
}
inline bool Ang_cmp(const Vector& A,const Vector& B)
{
return Cross(A,B)>0||(!Cross(A,B)&&Dot(A,A)<Dot(B,B));
}
class Computation_Geometry
{
private:
Vector va[N],vb[N];
public:
inline LL ConvexHull(Point *a,int n)
{
sort(a+1,a+n+1,cmp); n=unique(a+1,a+n+1)-a-1;
RI i,top=0; for (i=1;i<=n;++i)
{
while (top>1&&Cross(stack[top]-stack[top-1],a[i]-stack[top])<=0) --top;
stack[++top]=a[i];
}
LL temp=top; for (i=n-1;i;--i)
{
while (top>temp&&Cross(stack[top]-stack[top-1],a[i]-stack[top])<=0) --top;
stack[++top]=a[i];
}
if (n>1) --top; for (i=1;i<=top;++i) a[i]=stack[i]; return a[top+1]=a[1],top;
}
inline LL Minkowski_Sum(Point *a,CI n,Point *b,CI m)
{
RI i,tot; for (i=1;i<n;++i) va[i]=a[i+1]-a[i]; va[n]=a[1]-a[n];
for (i=1;i<m;++i) vb[i]=b[i+1]-b[i]; vb[m]=b[1]-b[m]; t[tot=1]=a[1]+b[1];
RI pa=1,pb=1; while (pa<=n&&pb<=m) ++tot,t[tot]=t[tot-1]+(Cross(va[pa],vb[pb])>=0?va[pa++]:vb[pb++]);
while (pa<=n) ++tot,t[tot]=t[tot-1]+va[pa++]; while (pb<=m) ++tot,t[tot]=t[tot-1]+vb[pb++]; return tot;
}
inline bool IsPointInConvexHull(Point *a,CI n,const Point& p)
{
if (Cross(p,a[1])>0||Cross(a[n],p)>0) return 0;
LL pos=lower_bound(a+1,a+n+1,p,Ang_cmp)-t-1;
if (pos==n) return Dot(p,p)<=Dot(a[n],a[n]);
return Cross(p-a[pos],a[pos%n+1]-a[pos])<=0;
}
}G;
int main()
{
//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
RI i; for (scanf("%lld",&n),i=1;i<=n;++i) scanf("%lld%lld",&A[i].x,&A[i].y);
for (scanf("%lld",&m),i=1;i<=m;++i) scanf("%lld%lld",&B[i].x,&B[i].y);
for (scanf("%lld",&k),i=1;i<=k;++i) scanf("%lld%lld",&C[i].x,&C[i].y);
n=G.ConvexHull(A,n); m=G.ConvexHull(B,m); k=G.ConvexHull(C,k);
num=G.Minkowski_Sum(A,n,B,m); num=G.ConvexHull(t,num);
num=G.Minkowski_Sum(C,k,t,num); num=G.ConvexHull(t,num);
//for (i=1;i<=num;++i) printf("%lld %lld\n",t[i].x,t[i].y);
for (st=t[1],i=1;i<=num;++i) t[i]=t[i]-st; num=G.ConvexHull(t,num);
for (scanf("%lld",&q),i=1;i<=q;++i)
scanf("%lld%lld",&p.x,&p.y),puts(G.IsPointInConvexHull(t,num,(p*3)-st)?"YES":"NO");
return 0;
}
关于闵可夫斯基和,还有一道有关的题目(竟然老早就做掉了233):JSOI2018]战争 还需要一个小小的转换
HHHOJ #151. 「NOI模拟 #2」Nagisa的更多相关文章
- HHHOJ #153. 「NOI模拟 #2」Kotomi
抽代的成分远远大于OI的成分 首先把一个点定为原点,然后我们发现如果我们不旋转此时答案就是所有位置的\(\gcd\) 如果要选择怎么办,我们考虑把我们选定的网格边连同方向和大小看做单位向量\(\vec ...
- Solution -「NOI 模拟赛」彩色挂饰
\(\mathcal{Description}\) 给定一个含 \(n\) 个点 \(m\) 条边的简单无向图,设图中最大点双的大小为 \(s\),则保证 \(s\le6\).你将要用 \(k\) ...
- Solution -「NOI 模拟赛」出题人
\(\mathcal{Description}\) 给定 \(\{a_n\}\),求一个 \(\{b_{n-1}\}\),使得 \(\forall x\in\{a_n\},\exists i,j\ ...
- 「CSP-S模拟赛」2019第四场
「CSP-S模拟赛」2019第四场 T1 「JOI 2014 Final」JOI 徽章 题目 考场思考(正解) T2 「JOI 2015 Final」分蛋糕 2 题目 考场思考(正解) T3 「CQO ...
- 「NOI十联测」深邃
「NOI十联测」深邃 要使得最大的连通块最小,显然先二分答案. 先固定1结点为根. 对于一个果实,显然是先处理子树中未分配的点,再向外延伸. 每个结点记录一个\(si[]\),表示子树中未分配的点数, ...
- 「NOI十联测」奥义商店
「NOI十联测」奥义商店 若lzz想花费最少的钱,那么显然要选择数目较少的颜色. 先考虑暴力的写法. 每次向两边统计,每个物品要求被买的概率可以由上一个物品推出. now=1;//now 被买概率 M ...
- 「NOI十联测」黑暗
「NOI十联测」黑暗 \(n\) 个点的无向图,每条边都可能存在,一个图的权值是连通块个数的 \(m\) 次方,求所有可能的图的权值和.(n≤30000,m≤15) 令\(ans[n][m]\)为n个 ...
- 「CSP-S模拟赛」2019第三场
目录 T1 「POI2007」山峰和山谷 Ridges and Valleys 题目 考场思路(几近正解) 正解 T2 「JOI 2013 Final」 现代豪宅 题目 考场思路(正解) T3 「SC ...
- 【模拟】HHHOJ#251. 「NOIP模拟赛 伍」高精度
积累模拟经验 题目描述 维护一个二进制数,支持如下操作 "+" 该数加 11 "-" 该数减 11 "*" 该数乘 22 "\&q ...
随机推荐
- php 逻辑题
越长大约发现,高中学的数学,都还给了数学老师,一点都没有留住. 最近遇到了一个 逻辑题,然后想了半天,后来做出来了,我就发现了,我可能是一个假的理科生.很简单的样子. 废话不说,看看这道题吧. /** ...
- C# Linq 使用总结
隐式类型匿名类型自动属性初始化器委托泛型泛型委托匿名方法Lambda表达式扩展方法迭代器LINQ System.Linq var arr = new[] { "c", " ...
- 学习笔记之自然语言处理(Natural Language Processing)
自然语言处理 - 维基百科,自由的百科全书 https://zh.wikipedia.org/wiki/%E8%87%AA%E7%84%B6%E8%AF%AD%E8%A8%80%E5%A4%84%E7 ...
- Python 集合(Set)、字典(Dictionary)
集合(Set) 集合是无序的,无序也就没有索引,不能进行索引相关的操作.无序,python解释器就不能通过索引(位置)区分集合中的相同元素,所以集合中不能有相同的元素. 集合用大括号{ }表示. 集 ...
- java 8大happen-before原则
1.单线程happen-before原则:在同一个线程中,书写在前面的操作happen-before后面的操作. 2.锁的happen-before原则:同一个锁的unlock操作happen-bef ...
- MyCat教程四:实现读写分离
本文我们来给大家介绍下通过MyCat来实现MySQL的读写分离操作 MyCat读写分离 一.读写分离配置 前面我们已经介绍过了mysql的主从同步和mycat的安装及相关配置文件的介绍,现在我们来 ...
- JavaScript数值和字符串、特殊字符
一.JavaScript数值 1.整数和浮点数 根据国际标准 IEEE 754,64 位浮点数格式的 64 个二进制位中,第0 位到第 51 位储存有效数字部分,第 52 到第 62 位储存指数部分, ...
- pip问题:ImportError: cannot import name main
问题描述 今天使用pip安装python包的时候,提示可以升级到最新版的pip,然后就升级了pip,从8.1.1到19.0.3,结果,就出现了下面的问题,pip不能用了: Traceback (mos ...
- 转:spring mvc 设置@Scope("prototype")
spring中bean的scope属性,有如下5种类型: singleton 表示在spring容器中的单例,通过spring容器获得该bean时总是返回唯一的实例prototype表示每次获得bea ...
- K-th Path CodeForces - 1196F
题目链接:https://vjudge.net/problem/CodeForces-1196F 题意:从图中找出第K短的最短路,最短路:从一个点到另一个的最短距离. 思路:题目说了,每两个点之间的边 ...