1 条题解
-
0
问题重述
给定一个 到 的排列 ,和一个长度为 由
U和D组成的字符串 。要求找到最长的子序列 ,使得对于每个 :
- 如果 ,则
- 如果 ,则
输出最大的 。
关键观察
1. 问题本质
这是带模式的最长交替子序列问题。模式由字符串 指定,决定了相邻元素之间必须是上升还是下降关系。
2. 暴力 DP
最直接的想法是定义: = 考虑前 个元素,匹配了模式的前 个字符,且以 结尾时的最小/最大值(取决于当前模式)
但状态数 对于 不可行。
核心解法
1. 状态重新设计
关键洞察:我们只关心对于每个模式位置 ,能够达到该位置的所有子序列的最后一个元素的值。
定义两个数组:
- = 匹配了模式的前 个字符,且最后一个字符满足当前模式要求(即如果 则要求上升)时,最后一个元素的最小值
- = 匹配了模式的前 个字符,且最后一个字符满足当前模式要求(即如果 则要求下降)时,最后一个元素的最大值
这样设计的目的是:
- 对于上升转移,我们希望最后一个元素尽可能小,为后续的上升留出空间
- 对于下降转移,我们希望最后一个元素尽可能大,为后续的下降留出空间
2. 转移过程
我们按顺序处理排列中的每个元素 :
对于每个模式位置 :
情况 1:如果 (下一个需要上升)
- 可以从 转移:如果 ,则
- 可以从 转移:如果 ,则
情况 2:如果 (下一个需要下降)
- 可以从 转移:如果 ,则
- 可以从 转移:如果 ,则
3. 初始化
- (实际上用一个极小值,表示还没有任何元素)
- (用一个极大值)
当我们处理第一个元素 时:
- 可以直接开始一个长度为 1 的子序列
- 根据 是
U还是D来初始化 或
算法优化
1. 单调性观察
随着 增加是非递减的(因为每次上升转移都会选择尽可能小的值) 随着 增加是非递增的(因为每次下降转移都会选择尽可能大的值)
2. 二分优化
利用单调性,我们可以用二分查找来快速找到能够进行转移的模式位置:
对于当前元素 :
- 如果下一个模式字符是
U,找到最大的 使得 或 - 如果下一个模式字符是
D,找到最大的 使得 或
这样可以将复杂度从 优化到 ,其中 是最终答案。
3. 实际实现
维护两个数组 和 ,初始时:
- ,
- 其他位置 ,
对于每个元素 :
- 在 数组中二分找到最大的 满足
- 在 数组中二分找到最大的 满足
- 设
- 如果 ,则
- 如果 ,则 (这里需要对称处理下降情况)
复杂度分析
- 对于每个元素:两次二分查找
- 总复杂度:,其中
- 由于 ,完全可行
总结
这道题的核心在于:
- 状态设计:用 和 分别记录两种模式下的最优结尾值
- 贪心思想:上升时选择尽可能小的结尾,下降时选择尽可能大的结尾
- 单调性利用: 数组单调不减, 数组单调不增
- 二分优化:利用单调性快速找到可转移的位置
通过将问题转化为维护两个具有单调性的数组,并利用二分查找进行高效转移,我们成功地将 的 DP 优化到了 ,解决了这个看似复杂的问题。
- 1
信息
- ID
- 4291
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 5
- 已通过
- 1
- 上传者