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 ...
随机推荐
- apache设置外网访问的方法 (服务器)
环境:windows server 2012 R2 apache 2.4 首先,找到apache配置文件httpd.conf,找到配置: 代码展示: <directory /> optio ...
- spring Boot 学习(七、Spring Boot与开发热部署)
一.热部署在开发中我们修改一个Java文件后想看到效果不得不重启应用,这导致大量时间 花费,我们希望不重启应用的情况下,程序可以自动部署(热部署).有以下四 种情况,如何能实现热部署.•1.模板引擎 ...
- SQL server中常用sql语句
--循环执行插入10000条数据 declare @ID intbeginset @ID=1 while @ID<=10000begininsert into table_name values ...
- Java NIO , AIO
New IO: 特点:不再阻塞 Channel , Buffer Async IO: 特点:异步
- [08001] Could not create connection to database server. Attempted reconnect 3 times. Giving up IDEA2019的database插件无法链接mysql的解决办法(08001错误)
[08001] Could not create connection to database server. Attempted reconnect 3 times. Giving up. 点击这里 ...
- only size-1 arrays can be converted to Python scalars
python版本:3.6.5 opencv版本:3.2.0 使用的jupyter notebook 源码如下: import cv2 import numpy as np import matplot ...
- Java自学-接口与继承 内部类
Java 内部类 内部类分为四种: 非静态内部类 静态内部类 匿名类 本地类 步骤 1 : 非静态内部类 非静态内部类 BattleScore "战斗成绩" 非静态内部类可以直接在 ...
- Myeclipse6.5迁移到IDEA
背景 myeclipse开发的javaweb项目用svn管理.现要转用idea开发.因为发现idea实在是太好用了.myeclipse6.5是个纯净版,用了两年,对于新手来说用myeclipse6.5 ...
- uni-app学习
1. 学习uni-app 1.1. 概述 号称一次编写多端运行的前端框架,架构图如下 对某些不同平台的特殊功能,可以通过条件进行自动编译,也就是写两套代码,不同的环境会选择不同代码编译 1.2. 推荐 ...
- window10体验terminal
体验window-terminal(preview),很不错可以直接登录服务器通过ssh 01.打开store 02.搜索terminal 03.体验ssh主机 04.很爽,可以ctrl + 鼠标滚轮 ...