1 条题解
-
0
题意分析
给定一个正整数序列 (非严格递增),要求:
- 求最长递增子序列的长度 。
- 求最多能取出多少个互不相交的长度为 的递增子序列。
- 如果允许 和 被多个子序列重复使用,最多能取出多少个长度为 的递增子序列。
第一部分:最长递增子序列长度
这是经典的 LIS 问题,可以用 的 DP 解决:
设 表示以第 个元素结尾的 LIS 长度: $ dp[i] = \max_{j < i, \, x_j \le x_i} \{ dp[j] \} + 1 $ 最终 。
第二部分:最多不相交的长度为 的 LIS
思路
我们要找多个长度为 的 LIS,且它们不能共享元素(除了第三问的特殊情况)。
关键观察:
- 每个元素只能属于一个 LIS。
- 一个 LIS 是序列中 值依次为 的路径。
建模为网络流
- 拆点:将每个位置 拆成两个点 和 ,连一条容量为 的边 ,表示每个位置只能用一次。
- 建边:如果 且 且 ,则从 向 连一条容量为 的边,表示可以接在后面形成 LIS。
- 源点和汇点:
- 从源点 向所有 的 点连容量为 的边。
- 从所有 的 点向汇点 连容量为 的边。
- 跑最大流,最大流的值就是最多能取出的不相交的长度为 的 LIS 数量。
第三部分:允许重复使用 和
修改容量
- 如果 ,那么 作为起点的边 容量改为 。
- 如果 ,那么 作为终点的边 容量改为 。
- 同时, 和 对应的拆点边 和 容量改为 (如果它们可能被多次使用)。
这样, 和 就可以被多个 LIS 重复使用。
样例验证
输入:
4 3 6 2 5-
计算 :
- (3→6)
- (2)
- (3→5 或 2→5)
-
第二问:
- 长度为 2 的 LIS 有:, ,
- 但互不相交时最多选 2 个(如 和 )
- 网络流最大流 = 2
-
第三问:
- 允许 和 重复使用
- 可以取:, , (都用到 3 或 5)
- 网络流最大流 = 3
输出:
2 2 3
算法步骤总结
- 读入 和序列 。
- 用 DP 计算 和 。
- 建图(拆点限制容量为 1):
- 容量 1
- 若 ,则 容量 1
- ()容量 1
- ()容量 1
- 跑最大流得到第二问答案。
- 修改与 和 相关的边容量为 (如果它们分别是某个 LIS 的起点/终点)。
- 再跑最大流得到第三问答案。
- 输出 、第二问答案、第三问答案。
复杂度分析
- , DP 可行。
- 网络流图节点数 ,边数 ,Dinic 算法 在 时可能稍大,但实际边数稀疏,可以接受。
- 1
信息
- ID
- 3931
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 2
- 已通过
- 1
- 上传者