垂直能见度问题的高效算法
在思考一个问题时,我意识到我需要创建一种有效的算法来解决以下任务: 问题:我们给了nnn边的二维方盒,其边与轴平行。我们可以从顶部进行调查。但是,也有mmm水平段。每段具有的整数yyy -协调(0≤y≤n0≤y≤n0 \le y \le n)和xxx坐标- (0≤x1<x2≤n0≤x1<x2≤n0 \le x_1 < x_2 \le n)并连接点(x1,y)(x1,y)(x_1,y)和(x2,y)(x2,y)(x_2,y)(看下图)。 我们想知道,对于框顶部的每个单元段,如果我们仔细观察该段,可以在框内垂直看到多深。 x∈{0,…,n−1}x∈{0,…,n−1}x \in \{0,\dots,n-1\}maxi: [x,x+1]⊆[x1,i,x2,i]yimaxi: [x,x+1]⊆[x1,i,x2,i]yi\max_{i:\ [x,x+1]\subseteq[x_{1,i},x_{2,i}]} y_i 示例:给定和分段,如下图所示,结果为。看看有多深的光线可以进入盒子。米= 7 (5 ,5 ,5 ,3 ,8 ,3 ,7 ,8 ,7 )n=9n=9n=9m=7m=7m=7(5,5,5,3,8,3,7,8,7)(5,5,5,3,8,3,7,8,7)(5, 5, 5, 3, 8, 3, 7, 8, 7) 对我们来说幸运的是,和都非常小,我们可以离线进行计算。米nnnmmm 解决此问题的最简单算法是蛮力:对于每个段,遍历整个数组并在必要时进行更新。然而,它给我们不是很可观。O(mn)O(mn)O(mn) 很大的改进是使用了一个片段树,该树能够在查询过程中最大化片段上的值并读取最终值。我不会进一步描述它,但是我们看到时间复杂度是。O((m+n)logn)O((m+n)logn)O((m+n) \log n) 但是,我想出了一个更快的算法: 大纲: 按坐标的降序对段进行排序(线性时间使用计数排序的变化)。现在注意,如果以前任何段都被任何段覆盖,则随后的任何段都不能再束缚通过该段的光束。然后,我们将从框的顶部到底部进行扫线。yyyxxxxxx …