Algorithm 对N行进行最小更改,使给定行成为所有行的子段
有一个长度为Algorithm 对N行进行最小更改,使给定行成为所有行的子段,algorithm,computational-geometry,Algorithm,Computational Geometry,有一个长度为l的线段LS和N其他线段,其端点如(a1,b1),(a2,b2)。。。(an,bn)[包括这两点]。范围内的所有值都小于或等于给定值k。找到需要在这些N线段中进行更改的最小单位,以使LS成为包含所有N线段的子线段。(假设所有线段都是水平的)例如 现在我正在做的是创建一个大小为k的数组,初始化为0,将范围的值增加1,然后最终找到大小为l的窗口的最大和,并从n*l中减去该和。但是,问题是当所有N线段都是全长时,即(1,k)。然后更新时间变为O(N*k)或O(N^2)如果N=k。有没有办法
l
的线段LS
和N
其他线段,其端点如(a1,b1),(a2,b2)。。。(an,bn)
[包括这两点]。范围内的所有值都小于或等于给定值k
。找到需要在这些N
线段中进行更改的最小单位,以使LS
成为包含所有N
线段的子线段。(假设所有线段都是水平的)例如
现在我正在做的是创建一个大小为k
的数组,初始化为0,将范围的值增加1,然后最终找到大小为l
的窗口的最大和,并从n*l
中减去该和。但是,问题是当所有N
线段都是全长时,即(1,k)
。然后更新时间变为O(N*k)
或O(N^2)
如果N=k
。有没有办法在少于O(N*k)
的时间内完成
感谢您的帮助。谢谢。这里有一个O(N log N+k)方法
首先,创建线段所有起点和终点的列表。对每个列表进行排序
想象一条从右向左的垂直线,其位置由i
给出。维护一个值s[i]
,该值是右端点大于i
的段数。因为您有一个右端点的排序列表,s[1:k]
可以在O(N+k)时间内计算出来。使用此方法,您可以填充一个数组L[i]
,其值为向左移动的单位数,以使所有线段从位置i
或更低开始L[k+1]=0
和L[i]=L[i+1]+s[i]
您可以从左到右执行类似的操作来计算R[j]
,向右移动的单位数,以使所有段结束在j
或更高的位置
现在,使所有线段重叠从i
到j
的间隔的总移动单位是R[i]+L[j]
这种方法的总时间是O(N logn)对端点进行排序,加上O(N+k)对算法的其余部分进行排序,总界限为O(N logn+k)
只要稍微小题大做,您就可以通过只计算区间端点附近的R[i]
和L[j]
将其改进为O(N logn+k)。这里是一个O(N logn+k)方法
首先,创建线段所有起点和终点的列表。对每个列表进行排序
想象一条从右向左的垂直线,其位置由i
给出。维护一个值s[i]
,该值是右端点大于i
的段数。因为您有一个右端点的排序列表,s[1:k]
可以在O(N+k)时间内计算出来。使用此方法,您可以填充一个数组L[i]
,其值为向左移动的单位数,以使所有线段从位置i
或更低开始L[k+1]=0
和L[i]=L[i+1]+s[i]
您可以从左到右执行类似的操作来计算R[j]
,向右移动的单位数,以使所有段结束在j
或更高的位置
现在,使所有线段重叠从i
到j
的间隔的总移动单位是R[i]+L[j]
这种方法的总时间是O(N logn)对端点进行排序,加上O(N+k)对算法的其余部分进行排序,总界限为O(N logn+k)
只要稍微小题大做,您就可以通过仅计算区间端点附近的
R[i]
和L[j]
将其改进为O(N log N)。在您的示例中哪个是LS?@cobarzan:LS没有显示,因为它没有范围,只是有一个长度。上例中的答案是2(提供了解释),在这种情况下,LS
的范围将是(2,3)
。但这不是必需的。在您的示例中,哪个是LS?@cobarzan:LS没有显示,因为它没有范围,只是有一个长度。上例中的答案是2(提供了解释),在这种情况下,LS
的范围将是(2,3)
。但这不是必须的。
N=4
l=2
k=8
ranges: (1,2), (2, 5) (1,8), (2,4)
1|2|3|4|5|6|7|8
---
-----
---------------
-----
ans: 2 (increase 1st line by 1 unit towards 3 and second line by 1 towards 2) or
(increase line 1 by 2 units upto 4)