Algorithm 接触段
谁能给我推荐一下这个算法吗 给定x轴上N个线段的起点和终点。 这些线段中有多少可以被垂直于它们的两条直线所接触,即使是在它们的边缘上 样本输入:Algorithm 接触段,algorithm,sorting,data-structures,graph-theory,overlapping,Algorithm,Sorting,Data Structures,Graph Theory,Overlapping,谁能给我推荐一下这个算法吗 给定x轴上N个线段的起点和终点。 这些线段中有多少可以被垂直于它们的两条直线所接触,即使是在它们的边缘上 样本输入: 3 5 2 3 1 3 1 5 3 4 4 5 5 1 2 1 3 2 3 1 4 1 5 3 1 2 3 4 5 6 样本输出: Case 1: 5 Case 2: 5 Case 3: 2 说明: 案例1:我们将在点2和4处绘制两条横穿X轴的线(平行于Y轴)。这两条线将接触所有五段 案例2:即使有一条线在2处穿过X轴,我们也可以接触到所有点 案
3
5
2 3
1 3
1 5
3 4
4 5
5
1 2
1 3
2 3
1 4
1 5
3
1 2
3 4
5 6
样本输出:
Case 1: 5
Case 2: 5
Case 3: 2
说明:
- 案例1:我们将在点2和4处绘制两条横穿X轴的线(平行于Y轴)。这两条线将接触所有五段
- 案例2:即使有一条线在2处穿过X轴,我们也可以接触到所有点
- 案例3:在这种情况下,触摸不可能超过两个点
1 ≤ N ≤ 10^5
0 ≤ a < b ≤ 10^9
1≤ N≤ 10^5
0≤ a
假设我们有一个有效支持以下操作的数据结构:
O(logn)
中的所有给定操作,那么我们就有了O(nlogn)
解决方案(我们对事件进行排序,并对排序后的数组进行一次遍历,为每个事件对此数据结构进行常量查询)
那么我们如何实现这个数据结构呢?嗯,分段树在这里很好用。添加线段就是将一个线段添加到特定范围。删除一个线段就是从特定范围内的所有元素中减去一个线段。获取最大值只是段树上的标准最大值操作。因此,我们需要一个支持两种操作的段树:向一个范围添加一个常量,并获取整个树的最大值。它可以在每次查询的O(logn)
时间内完成
还有一点需要注意:标准段树要求坐标很小。我们可以假设它们永远不会超过2*n
(如果不是这样,我们可以压缩它们) 一个O(N*max(logN,M))
解决方案,其中M是中等段大小,在公共Lisp中实现:
其思想是首先从左到右计算每个感兴趣的点上一条直线所接触的线段数(openleft-to-right
lisp代码)。成本:O(NlogN)
然后,从右到左,再次在每个有趣的点p
,计算直线的最佳位置,考虑p
的段完全向右(在lisp代码上从右到左打开)。成本O(N*max(logN,M))
然后,只需寻找两个值之和最大的点。成本O(N)
代码几乎没有经过测试,可能包含bug。此外,我还没有费心处理分段数为零时的边缘情况
问题可以在每个测试用例的O(Nlog(N))时间内解决
请注意,存在两条垂直线的最佳位置,每条垂直线都穿过一些线段端点
压缩段的坐标。更多信息在什么是
构建一组已排序的段端点X
按a\u i对段进行排序[a\u i,b\u i]
设Q是一个优先级队列,它存储到目前为止处理的段的右端点
设T是建立在x坐标上的最大间隔树。一些有用的阅读材料
对于每个段,进行[a_i,b_i]-范围按1递增查询到T。它允许在[a,b]
正好垂直于它们的两条线
?那么这两条线将平行于y轴,它们是否需要在整数点处穿过x轴?@PhamTrung,是的,它必须交叉或接触。在整数点处?“还有什么呢?”萨尔瓦说得对,然后呢?我不认为这是件小事。你不能强求,否则复杂性太大big@salva不,接触最多的两个点不一定是最佳点。考虑例如:(1, 3)、(2, 3)、(2, 4)、(5, 6)、(5, 7)、(5, 8)、(5, 9)。您的想法将返回5和6,并触摸4个段,但正确答案之一是1和5。这不是基于线扫描算法吗?@VikasGupta是的,它是。@kraskevich可以告诉您为什么这种方法在某些测试用例中失败:1。做心脏按压2。那么每一里