【问题标题】:Counting the strictly increasing sequences计算严格递增的序列
【发布时间】:2014-11-05 19:28:05
【问题描述】:

我将 N 根蜡烛从左到右对齐。从左边算起的第 i 个蜡烛的高度为 Hi 和颜色 Ci,一个从 1 到给定 K 的整数,即颜色的数量。

问题:有多少严格递增(高度)的彩色子序列?如果 K 种颜色中的每一种在子序列中至少出现一次,则该子序列被认为是彩色的。

For Ex: N=4 k= 3
      H   C
      1    1
      3    2  
      2    2
      4    3 

只有两个有效的子序列是 (1, 2, 4) 和 (1, 3, 4)

我认为这是 Fenwick Tree 的问题,请提供一种处理此类问题的方法

【问题讨论】:

  • 对 N 和 K 有什么限制?
  • 为什么 (1,2,3,4) 不是一个有效的子序列?它的高度严格增加,并且每种颜色至少包含一次。
  • @Mshnik : H3

标签: algorithm


【解决方案1】:

暂时,让我们忘记颜色。所以问题更简单:计算增加子序列的数量。这个问题有一个标准的解决方案:
1.将每个值映射到[0...n - 1]范围。
2. 假设f[value] 是具有value 作为最后一个元素的递增子序列的数量。
3. 最初f 填充为0。
4. 之后,从左到右遍历所有数组元素并执行以下操作:f[value] += 1 + get_sum(0, value - 1)(意味着将此元素添加到所有可能的子序列中,使它们保持严格递增),其中value 是数组的当前元素和get_sum(a, b) 返回f[a] + f[a + 1] + ... + f[b] 的总和。
5. 答案是f[0] + f[1] + ... + f[n - 1].
使用二叉索引树(又名 Fenwick 树),可以在O(log n) 中进行get_sum 操作,得到O(n log n) 的总时间复杂度。

现在让我们回到最初的问题。考虑到颜色,我们可以计算f[value, mask] 而不是f[value](即以value 作为最后一个元素和mask(它是一个位掩码,显示哪些颜色是目前)颜色)。然后每个元素的更新如下所示:

for mask in [0...2^K - 1]:
     f[value, mask or 2^(color[i] - 1)] += 1 + get_sum(0, value - 1, mask)

答案是f[0, 2^K - 1] + f[1, 2^K - 1] + ... + f[n - 1, 2^K - 1]

您可以使用与更简单问题相同的想法来维护2^K 二叉索引树以实现O(n * log n * 2^K) 时间复杂度。

【讨论】:

  • 当高度为 k 的数组的第一个元素出现时 get_sum(0,k-1) (因为 f[i] i
  • 您能解释一下 get_sum 的工作原理,它将如何清除所有内容
  • @user4213270 这只是对二叉索引树的一次查询。
  • 掩码或 2^(color[i] - 1) 为什么或运算符
  • @user4213270 第i个元素被添加到序列中,所以它的颜色应该被添加到序列中的颜色集合中。
猜你喜欢
  • 1970-01-01
  • 2020-12-30
  • 2021-04-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-14
  • 1970-01-01
  • 1970-01-01
  • 2021-03-22
相关资源
最近更新 更多