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)