【问题标题】:The number of increasing subsequences using "The longest increasing subsequence algorithm (nlgn)"使用“最长递增子序列算法(nlgn)”的递增子序列数
【发布时间】:2025-12-14 07:00:01
【问题描述】:

供参考:我正在解决嵌套娃娃问题:http://uva.onlinejudge.org/index.php?option=onlinejudge&page=show_problem&problem=2353

我已经写了找到最长递增子序列的部分(nlgn 版本)。例如,如果序列如下:1 2 3 1 2 1

  1. 我找到了最大的子序列:“1 2 3”并将其从 原始序列。序列变为 1 2 1。

  2. 我找到了最大的子序列:“1 2”,然后我再次将其删除。序列变为 1。

  3. 我找到了最大的子序列:“1”,然后将其删除。序列变为空。

所以答案是 3、3 个总递增子序列

我的问题是我得到了 TLE(时间限制),我需要一种更好的方法来计算子序列。有一个关于使用“迪尔沃斯定理”的提示,但我不知道如何应用它。

【问题讨论】:

    标签: algorithm


    【解决方案1】:

    算法

    如果我正确理解了这个问题,您正在尝试找到可以打包每个娃娃的最小嵌套娃娃数量,并且您的算法是在每个阶段贪婪地制作最大的娃娃(最大的意思是它包含最多件)并重复,直到所有的娃娃都被打包。

    换句话说,您正在从部分有序集合中构建链。

    Dilworth's theorem 说:

    任何反链中元素的最大数量等于最小值 集合的任何分区中的链数为链

    因此您可以通过计算单个反链中的元素来计算链的数量。

    您可以以与您目前正在做的非常相似的方式构建反链,通过按宽度以降序排列娃娃,然后在高度内找到最长的递增子序列。

    注意,使用这种方法,您可以通过测量反链的长度来得到答案,并且您只需要运行一次最长递增子序列算法,因此它应该会快很多。

    示例

    在您的 (1, 1), (1, 1), (2, 2), (3, 3), (1, 1), (2, 2), (1, 1) 的例子中,我们首先按宽度降序排列:

    (3, 3), 
    (2, 2), 
    (2, 2), 
    (1, 1), 
    (1, 1), 
    (1, 1), 
    (1, 1)
    

    然后提取高度:

    3,2,2,1,1,1,1
    

    然后找到最长的递增子序列(注意每个元素必须与前一个相同或更高,所以严格来说你会找到最长的非递减子序列):

    1,1,1,1
    

    这个长度为 4,所以答案是 4。

    【讨论】:

    • 谢谢!你能提供一个小例子吗?例如,如果序列是 (1, 1), (1, 1), (2, 2), (3, 3), (1, 1), (2, 2), (1, 1) 答案应该是 4. 最长子序列的长度为 3。或 (1, 1), (1, 1), (1, 1), (1, 1), (1, 1) 答案是 5,最长子序列是 5
    • @nemo 我已将您的示例添加到答案中 - 这会让事情更清楚吗?
    • 非常感谢!!!如果我做不好,我会实施它并回到这里大声笑
    • 1,1,1,1如何成为“递增子序列”?这些不是增加的数字。在 3 2 2 1 1 1 1 中,最长的递增子序列是 2 3 和 1 2。