1 条题解

  • 0
    @ 2025-10-23 20:49:34

    题意分析

    给定一个正整数序列 x1xnx_1 \sim x_n(非严格递增),要求:

    1. 求最长递增子序列的长度 ss
    2. 求最多能取出多少个互不相交的长度为 ss 的递增子序列。
    3. 如果允许 x1x_1xnx_n 被多个子序列重复使用,最多能取出多少个长度为 ss 的递增子序列。

    第一部分:最长递增子序列长度 ss

    这是经典的 LIS 问题,可以用 O(n2)O(n^2) 的 DP 解决:

    dp[i]dp[i] 表示以第 ii 个元素结尾的 LIS 长度: $ dp[i] = \max_{j < i, \, x_j \le x_i} \{ dp[j] \} + 1 $ 最终 s=maxi=1ndp[i]s = \max_{i=1}^n dp[i]


    第二部分:最多不相交的长度为 ss 的 LIS

    思路

    我们要找多个长度为 ss 的 LIS,且它们不能共享元素(除了第三问的特殊情况)。

    关键观察

    • 每个元素只能属于一个 LIS。
    • 一个 LIS 是序列中 dpdp 值依次为 1,2,,s1, 2, \dots, s 的路径。

    建模为网络流

    1. 拆点:将每个位置 ii 拆成两个点 iiii',连一条容量为 11 的边 (i,i)(i, i'),表示每个位置只能用一次。
    2. 建边:如果 j<ij < ixjxix_j \le x_idp[j]+1=dp[i]dp[j] + 1 = dp[i],则从 jj'ii 连一条容量为 11 的边,表示可以接在后面形成 LIS。
    3. 源点和汇点
      • 从源点 SS 向所有 dp[i]=1dp[i] = 1ii 点连容量为 11 的边。
      • 从所有 dp[i]=sdp[i] = sii' 点向汇点 TT 连容量为 11 的边。
    4. 跑最大流,最大流的值就是最多能取出的不相交的长度为 ss 的 LIS 数量。

    第三部分:允许重复使用 x1x_1xnx_n

    修改容量

    • 如果 dp[1]=1dp[1] = 1,那么 x1x_1 作为起点的边 (S,1)(S, 1) 容量改为 \infty
    • 如果 dp[n]=sdp[n] = s,那么 xnx_n 作为终点的边 (n,T)(n', T) 容量改为 \infty
    • 同时,x1x_1xnx_n 对应的拆点边 (1,1)(1, 1')(n,n)(n, n') 容量改为 \infty(如果它们可能被多次使用)。

    这样,x1x_1xnx_n 就可以被多个 LIS 重复使用。


    样例验证

    输入:

    4
    3 6 2 5
    
    1. 计算 dpdp

      • x=[3,6,2,5]x = [3, 6, 2, 5]
      • dp[1]=1dp[1] = 1
      • dp[2]=2dp[2] = 2(3→6)
      • dp[3]=1dp[3] = 1(2)
      • dp[4]=2dp[4] = 2(3→5 或 2→5)
      • s=2s = 2
    2. 第二问

      • 长度为 2 的 LIS 有:[3,6][3,6], [3,5][3,5], [2,5][2,5]
      • 但互不相交时最多选 2 个(如 [3,6][3,6][2,5][2,5]
      • 网络流最大流 = 2
    3. 第三问

      • 允许 x1=3x_1=3x4=5x_4=5 重复使用
      • 可以取:[3,6][3,6], [3,5][3,5], [2,5][2,5](都用到 3 或 5)
      • 网络流最大流 = 3

    输出:

    2
    2
    3
    

    算法步骤总结

    1. 读入 nn 和序列 xx
    2. 用 DP 计算 dp[i]dp[i]ss
    3. 建图(拆点限制容量为 1):
      • (i,i)(i, i') 容量 1
      • j<i,xjxi,dp[j]+1=dp[i]j < i, x_j \le x_i, dp[j]+1=dp[i],则 (j,i)(j', i) 容量 1
      • SiS \to idp[i]=1dp[i]=1)容量 1
      • iTi' \to Tdp[i]=sdp[i]=s)容量 1
    4. 跑最大流得到第二问答案。
    5. 修改与 x1x_1xnx_n 相关的边容量为 \infty(如果它们分别是某个 LIS 的起点/终点)。
    6. 再跑最大流得到第三问答案。
    7. 输出 ss、第二问答案、第三问答案。

    复杂度分析

    • n500n \le 500O(n2)O(n^2) DP 可行。
    • 网络流图节点数 2n+22n+2,边数 O(n2)O(n^2),Dinic 算法 O(V2E)O(n4)O(V^2 E) \approx O(n^4)n=500n=500 时可能稍大,但实际边数稀疏,可以接受。
    • 1

    信息

    ID
    3931
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    2
    已通过
    1
    上传者