1 条题解
-
0
自动搬运
来自洛谷,原作者为

first_fan
Just Do It,But Not Just Do It.搬运于
2025-08-24 21:45:18,当前版本为作者最后更新于2019-09-15 10:24:35,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
本题题意简单:给出两组大小为n的点集,问点集A中任取三点形成的三角形围住点集B中点的数量,以及B包A的数量。
其实题目可以进一步简化:我们来看一幅图(样例解释)

我们可以主观感受一下,红点被蓝点包了一个,蓝点被红点包了俩。
回想一下,我们是怎么判断的呢?一个个三角形枚举吗?
多感受几次,我们发现:如果一个点被异色点围成的一个多边形围住,那么它就被捕了(如下图)。但是为什么?

别忘了,当你把所有可能的三角形围出来的时候,就注定把这些点围成的多边形覆盖,因为所有的三角形边中一定包含了这个多边形的边。还是以图举例。

显然这个五个点围出了五边形(为了美观,有部分三角形未画出)
直入主题,这样的多边形我们称之为。那么我们现在需要的就是
判断点是否在凸包内了。关于凸包,网上已有详细的讲解,此处不作赘述。
那么此题中,我们采用的是常规的二分判断叉积法判断。
//取其中的一个点,他和其他点可以组成n-2个三角形,利用二分判断差积, //判断他是在当前三角形内,还是在三角形左边,还是在三角形右边,或者是三角形外。 int check(dot b,int n) { int l=1; int r=n-2; while(l<=r) { int mid=(l+r)>>1; ll cr1=(bor[mid]-bor[0])*(b-bor[0]); ll cr2=(bor[mid+1]-bor[0])*(b-bor[0]);//叉积 if(cr1>=0&&cr2<=0)//也就是说此时该点b在bor[mid]上方或其线上,又在bor[mid+1]下方或其线上 { if((bor[mid+1]-bor[mid])*(b-bor[mid])>0) //bor[mid]->bor[mid+1] 与 bor[mid]->b 的叉积 { return true; }//如果此时叉积大于等于0,说明该点b在该三角形内部或者边界上 //经过卡数据,此题边界点不计入内。 return false;//点在三角形外部 } else if(cr1<0) //如果该点在bor[mid]下方,那么把上边界缩小到mid-1 { r=mid-1; } else //如果该点在bor[mid+1]上方,那么把下边界拉至mid+1 { l=mid+1; } } return false; }那么有了判断法,我们就先求出AB两点集的凸包,并且用对集的点一个个代入判断即可,这是思维量最小的方式。
- 不得不提的一点:此题的边界不算入内,有一个点恰好点在凸包边界上,不能计入内。
为不影响阅读,完整代码请移步此处
- 1
信息
- ID
- 2163
- 时间
- 1000ms
- 内存
- 125MiB
- 难度
- 5
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者