计算由两条垂直线切割的水平线段

时间:2015-04-10 14:57:02

标签: algorithm

给定N个水平线段,其中包含起点和终点(即A和B),对重叠标准没有限制。这意味着我们有从(A,0)到(B,0)的线段。现在我们可以绘制两条穿过这些线的垂直线。我们需要找到这两条线可以交叉的最大线段。 (如果垂直线接触任何水平线段,也要计算)

示例:假设我们有5个线段:

2 3
1 3
1 5
3 4
4 5

然后我们将绘制两条线(平行于Y轴)在第2点和第4点与X轴交叉。这两条线将触及所有五个线段。所以答案为5。

但我们假设我们有3个线段:

1 2
3 4
5 6

然后回答为2,因为在这种情况下不可能触摸超过两点。

如何解决这个问题?请帮忙。

注意1≤N≤10^ 5且0≤A<1。 B≤10^ 9

1 个答案:

答案 0 :(得分:0)

以下是此问题的一些提示。

提示1

将变量计数设置为0。

现在对开始和结束事件进行排序,并按递增顺序循环事件。

如果您看到开始事件,请将计数增加1。

如果您看到结束事件,请将计数减少1。

在算法的每一步,count都会给出与当前x位置重叠的区间数。

提示2

上面的提示显示了如何找到重叠最多间隔的单行。

但是,我们想要找到2行。所以我们需要做的是能够找到跨越最多间隔的第二条线 - 不包括触及第一条线的间隔。

您可以使用具有延迟传播的分段树(C ++代码here)。这允许您在时间O(logn)中添加间隔/查询最大值。

您可以将此与提示1结合使用,只有在看到结束事件时才向段树添加间隔。

在伪代码中,完整的算法将是:

For each event in sorted order:
   if event.type==start: count += 1
   if event.type==end: count -= 1 and update segment tree to add 1 to all points in range event.start to event.end
   current_value = count + maximum value in segment tree
   best_value = max(best_value,current_value)  

初始排序的总体复杂度为O(nlogn),加上扫描的O(nlogn)以找到最佳线对。

相关问题