【问题标题】:Efficient way to find min(max(A[L], A[L+1],...,A[R]), min(B[L], B[L+1],…, B[R]))找到 min(max(A[L], A[L+1],...,A[R]), min(B[L], B[L+1],..., B[R] 的有效方法))
【发布时间】:2021-09-21 17:30:15
【问题描述】:

给定 2 个数组 A[N] 和 B[N]。对于每一个 0

min(max(A[L], A[L+1],...,A[R]), min(B[L], B[L+1],…, B[R])) 

对于 L

ans[L] 是 L 的答案。
例如,
N = 3
A[3] = {3, 2, 1}
B[3] = {3, 2, 3}
所以,答案是
答案[0] = 3
答案[1] = 2
答案[2] = 1

很明显,蛮力可以跑得很快。
然后,我尝试使用 Sparse table、Segment Tree 或 Binary Indexed Tree(我们不需要更新任何东西,所以我选择了 Sparse Table)。但是对于每个L,我们不知道R,所以我需要跑到数组的末尾,这和蛮力没有什么不同。

有没有针对这个问题的有效算法或数据结构??

P/s:对不起我的英语不好。

【问题讨论】:

  • 如果你的最小值和最大值是正确的,你能解释一下你是如何得到 ans[2] = 3 的吗?
  • 还有R在这里的意义是什么?似乎 R 总是被假定为 N。否则你应该有类似 ans[L][R]
  • @Surt,抱歉,这是我的错。
  • @SomeDude,R只是从L到N的一个变量,每次都要计算min(max(A[L], A[L+1],...,A[ R]), min(B[L], B[L+1],…, B[R])) 。 ans[L] 是其中的最大值。你可以看到 ans[0] = 3 (L=R=0)。因此,R 并不总是等于 N。

标签: algorithm max min


【解决方案1】:

使用Sparse table A是单调递增的,B是单调递减的,所以我们需要找到交叉点,让它们的最小值中的最大值...

未经测试的伪python代码

stA = SparseTable(A);
stB = SparseTable(B);

for (i in range(len(A))
  r = len(B)
  l = i

  a = stA.max(l,r)
  b = stB.min(l,r)

  # binary search for crossing point
  while (l != r)
    m = l + (r-l)//2  # integer division 
    a = stA.max(l,m)
    b = stB.min(l,m)
    if (b > a)
      l = m + 1
    else
      r = m

  ans[i] = min(a,b) # might be off-by-one m?

【讨论】:

    【解决方案2】:

    max(A[L], A[L+1], ..., A[R]) 在 L 中不增加,在 R 中不减小。相反, min(B[L], B[ L+1], ..., B[R]) 在 L 中不减,在 R 中不增加。由此可知,从 L 到 R 中的 argmax 的函数是不减的。最后一个成分是两个队列,一个可以报告最大值,一个可以报告最小值,以快速计算滑动窗口聚合。

    【讨论】:

      猜你喜欢
      • 2020-01-02
      • 2015-04-29
      • 2021-12-10
      • 1970-01-01
      • 1970-01-01
      • 2015-03-11
      • 2020-09-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多