在思考一个问题时,我意识到我需要创建一种有效的算法来解决以下任务:
问题:我们给了边的二维方盒,其边与轴平行。我们可以从顶部进行调查。但是,也有水平段。每段具有的整数 -协调()和坐标- ()并连接点和(看下图)。
我们想知道,对于框顶部的每个单元段,如果我们仔细观察该段,可以在框内垂直看到多深。
示例:给定和分段,如下图所示,结果为。看看有多深的光线可以进入盒子。米= 7 (5 ,5 ,5 ,3 ,8 ,3 ,7 ,8 ,7 )
对我们来说幸运的是,和都非常小,我们可以离线进行计算。米
解决此问题的最简单算法是蛮力:对于每个段,遍历整个数组并在必要时进行更新。然而,它给我们不是很可观。
很大的改进是使用了一个片段树,该树能够在查询过程中最大化片段上的值并读取最终值。我不会进一步描述它,但是我们看到时间复杂度是。
但是,我想出了一个更快的算法:
大纲:
按坐标的降序对段进行排序(线性时间使用计数排序的变化)。现在注意,如果以前任何段都被任何段覆盖,则随后的任何段都不能再束缚通过该段的光束。然后,我们将从框的顶部到底部进行扫线。
现在让我们介绍一些定义: -unit segment是扫描中的虚构水平线段,其坐标是整数且长度为1。在扫描过程中,每个线段都可能未标记(即,从框顶部可以到达此细分)或标记(相反的情况)。考虑一个单位段,其中,始终未标记。让我们还介绍集合。每组将包含一个连续的连续标记的单位片段(如果有)的完整序列,其后带有未标记的 分割。
我们需要一个能够在这些段上运行并高效设置的数据结构。我们将使用由包含最大单位段索引(未标记段的索引)的字段扩展的find-union结构。
现在,我们可以有效地处理细分了。假设我们现在按顺序考虑第个分段(称为“查询”),该分段以开始,以结尾。我们需要找到所有包含在第个分段内的未标记分段(这些分段正是光束将在其上结束的分段)。我们将执行以下操作:首先,我们在查询中找到第一个未标记的段(找到其中包含的集合的代表,并获取该集合的最大索引,根据定义,该索引为未标记的段)。然后这个指数 在查询内,将其添加到结果(此细分结果是)并标记这个索引(联盟含有集和)。然后重复此过程,直到找到所有未标记的段,即下一个“ 查找”查询给出索引。
请注意,每个find-union操作仅在两种情况下完成:要么我们开始考虑一个段(可能发生次),要么我们刚刚标记了一个单位段(这可能发生次)。因此,总体复杂度为(是逆阿克曼函数)。如果不清楚,我可以详细说明。如果我有空的话,也许可以添加一些图片。x n O ((n + m )α (n ))α
现在我到达了“墙”。尽管似乎应该有一个线性算法,但我无法提出线性算法。因此,我有两个问题:
- 是否存在线性时间算法(即)来解决水平线段可见性问题?
- 如果不是,那么可见性问题是的证明是什么?