一个没啥卵用的新(?)算法

这是某天做模拟赛的时候,因为遇到了没见过的问题,瞎胡的算法。

严格意义上来说好像不能算算法,应该是一种新的做法。

upd on 01.29.23: 哈哈,寄吧,假了,被日语酱插了,给了一个凸多边形也会相交的例子。

我想了一下,具体就是,对于任意两条相邻边,钦定斜率绝对值更大的一条边,算 \(\arctan |k|\),如果大于了两边夹角,两条边的矩形就会相交。

寄。


众所周知计算几何里有一个叫做“判断是否在任意多边形内部”的问题。

考试的时候读错题以为问题就是这个板子,但是不会,于是思考了很久有了些想法,后面经过 EI 的提醒完善了一下。

这个问题一般有两种通用的解决方法:Ray casting algorithm 和 Winding number algorithm。

感觉很厉害,我不太清楚复杂度,但是听说都要扫一遍?好像有 \(O(\log n)\) 单次询问的做法。

但是我其实不太会,感觉也理解不了那么高深的做法,想自己搞一个做法出来,然后就有了这玩意儿:

具体来说这个做法能够在 \(O(n \log n)\) 带一个我现在还不知道多大的常数的时间复杂度内,离线完成以下问题的判定:

给定一个由 \(n\) 条边组成的 Polygon,\(m\) 个 Point,要求 Check 每个 Point 是否在 Polygon 内。

\(1\le n, m \le 1e5\)(即假定 \(n, m\) 同级),保证多边形为凸多边形

首先有一个直观的想法,多边形可能有很多斜着的边,这不好判断。

我们想做的事情就是,能不能转化成只考虑水平/竖直方向的情况呢?

于是想到,对于每一个边,我们画一个以它为对角线的矩形:

类似这样:

polygon-1.png

然后中间这一大坨就很好判断了,一看就是个扫描线板子的形状。

先按照 \(x\) 坐标分组存一下点,

然后直接对中间这一坨做一次扫描线,因为矩形不会相交,所以线段树都不需要了,直接用一个 vector/set 二分搞一下即可。

然后我们把这些已经被标记的点删去,中间的部分就处理完了。

差不多长成这样:

polygon-2.png

不过要记得扫描线的时候下标得是按点集覆盖的下标来(不然会漏判

于是我们现在要考虑的就是外面的部分。

其实也比较简单,也是扫描线扫过去,然后因为扫描线上有标记的一段一定是一个单独的矩形,所以可以额外记下这一段是哪一个矩形,然后就是暴力做。

扫到一个点,判一下它在这个矩形对角线的哪一侧,看看是不是在矩形内即可。

因为每个点只会被访问到一次,所以这玩意儿理论最坏是 \(O(n \log n)\) 的,

注意到如果是任意多边形,有可能我们画出来的矩形会相交,这个做法就假了,所以我正在考虑能不能扩展。

不知道正确性如何,如果错了欢迎开喷(

实现我先咕咕咕着,有时间了再写。

这个做法应该是被那个著名虐狗题 Stars in your windows 启发的。

画矩形这个,可能是我哪天无聊想出来的。


最后更新: May 9, 2023