我试图了解可用于计算一组轴对齐矩形的并集面积的算法。
我要遵循的解决方案在这里:http://tryalgo.org/en/geometry/2016/06/25/union-of-rectangles/
我不了解的部分是:
段树是此数据结构的正确选择。它具有复杂度O(logn) 用于更新操作和O(1) 用于查询。我们需要使用每个节点的分数来扩展分段树,并具有以下属性。
- 每个节点对应一个y间隔,它是该节点范围内所有索引上基本y间隔的并集。
- 如果节点值为零,则得分是后代得分的总和(如果节点是叶则为0)。
- 如果节点值为正,则得分为与该节点相对应的y间隔的长度。
我们如何在O(n log n)中实现呢?
我的想法是创建一个线段树,并在扫线时遇到范围(y范围为矩形的高度)时更新每个范围的值。然后对于每个间隔(在已排序的x数组中,两个连续的元素,通过查看段树中所有元素的总和,将Δx乘以该间隔内y范围的总长度)
这仍然会使我们在细分树的基础中具有max(y)-min(y)个元素。
因此,我不确定这是O(n log n)-其中n是矩形的数量。
非常感谢您的帮助。
谢谢!
答案 0 :(得分:3)
根据您的理解,您将创建一个在基础上具有11-1 = 10个节点的段树,如下所示:
请注意,我们的基础节点只有9个,因为第一个节点的间隔为[1,2],下一个节点的间隔为[2,3],依此类推
当您输入某个矩形时,您将根据其y坐标更新其范围,因此在x = 0上遇到第一个矩形后,您的细分树如下所示:
我们还需要使用惰性传播来更新树上的活动间隔,因此所有活动间隔将为总和贡献1。
因此,当前方法的复杂度类似于O(K log K),其中K = max(y)-min(y)
我们可以将其简化为O(n log n),其中n是矩形的数量。
请注意,只有重要的y坐标存在,因此在此示例中1,3,6,11
还要注意,这样的坐标最多2 * n
因此我们可以将所有坐标映射到一些整数,以便它们更适合分段树。
这称为坐标压缩,可以通过以下方式完成:
因此在我们的示例中为:
[1,3,6,11]
[1,3,6,11]
mp[1]=1, mp[3]=2, mp[6]=3, mp[11]=4
因此,现在的算法保持不变,但是我们只能使用基数最多为2 * n个节点的段树。
我们还需要稍微修改段树, 而不是保持打开或关闭哪些y坐标,我们现在保持打开或关闭哪些y坐标的间隔
因此,对于所有y的唯一排序值,我们将具有间隔[y0,y1],[y1,y2],...的节点。
所有节点也将对总和(如果它们在范围内且处于活动状态)贡献y [i] -y [i-1]而不是一个。
所以我们的新细分树将是这样的:
答案 1 :(得分:0)
我们如何在O(n log n)中实现这一目标?
考虑每个矩形,您将更新二进制段树中的范围[x,y]。本质上发生的是,你是
假设您找到的x节点为[x,a],并且其父节点为[z,a],并且该父节点具有同级节点[a,b]。显然,如果y不在[a,b]下,则将覆盖[a,b]的整个范围,因此您要递增此节点,而不是[a,b]子树下的所有单个段节点。
结果,搜索/更新过程看起来像这样。
基本上,在进入一个节点之前,请决定是否更新其同级。
您决定是否更新的节点数是log(N)(对于x)+ log(N)(对于y)。