题面

一道线性 DP 好题。

设 \(dp_{i,j}\) 表示在所有 \(a_{1\dots i}\),\(b_{1\dots j}\) 的子序列中,以 \(b_j\) 结尾的最长公共上升子序列的最大长度。

转移的时候考虑 \(2\) 种情况:

  • 若不选择 \(a_i\),则 \(dp_{i,j}=dp_{i-1,j}\);
  • 若选择 \(a_i\),则 \(dp_{i,j} = \max_{1\leq k \leq j,b_k < b_j}\{dp_{i-1,k}\}+1\)。又因为有 \(a_i=b_j\),所以 \(dp_{i,j} = \max_{1\leq k \leq j,b_k < a_i}\{dp_{i-1,k}\}+1\)。

转移的代码:

for (int i = 1; i <= n; i+=1)
for (int j = 1; j <= n; j+=1)
{
dp[i][j] = dp[i - 1][j];
if (a[i] == b[j])
{
int maxdp = 0;
for (int k = 1; k < j; k+=1)
if (b[k] < a[i])
maxdp = max(maxdp, dp[i - 1][k]);
dp[i][j] = max(dp[i][j], maxdp + 1);
}
}

这样转移的复杂度其实是 \(O(n^3)\) 的,明显会超时。

于是我们考虑优化,即对转移的代码进行等价变形。

我们发现,第三重循环能够转移的状态其实是所有 小于 \(j\) 的 \(k\),且 \(b_k < a_i\)。因为 \(a_i\) 的值是不变的,所以我们可以预处理出所有 \(dp_{i,k}(k<j)\) 的最大值,即 \(dp_{i,j}\) 的前缀最大值。

具体做法就是将变量 maxdp 移到第二层循环外,然后如果 \(b_j < a_i\) 就将 maxdp 与 \(dp_{i,j}\) 取 \(\max\)。

完整代码:

#include <bits/stdc++.h>

using namespace std;

const int N = 3003;

int n, m;
int a[N], b[N], dp[N][N]; int main()
{
cin >> n;
for (int i = 1; i <= n; i+=1)
cin >> a[i];
for (int i = 1; i <= n; i+=1)
cin >> b[i];
for (int i = 1; i <= n; i+=1)
{
int maxdp = 0;
for (int j = 1; j <= n; j+=1)
{
dp[i][j] = dp[i - 1][j];
if (a[i] == b[j]) dp[i][j] = max(dp[i][j], maxdp + 1); //转移
if (b[j] < a[i]) maxdp = max(maxdp, dp[i][j]); //前缀最大值
}
}
int ans = 1;
for (int i = 1; i <= n; i+=1) ans = max(ans, dp[n][i]);
cout << ans << endl;
return 0;
}

题解【AcWing272】最长公共上升子序列的更多相关文章

  1. Acwing272 最长公共上升子序列

    题目大意:给定两个大小为n的数组,让你找出最长公共上升子序列的长度. 分析:这是一个比较好的dp题,LIS和LCS两大经典线性dp问题相结合,简称LCIS. 代码(O(n*n*n)写法): #incl ...

  2. CH5101 LCIS(最长公共上升子序列) 题解

    每日一题 day16 打卡 Analysis 设F[i,j]表示A[1..i]与B[1..j]并且以B[j]结尾的两段最长公共上升子序列,那么我们可以发现这样的转移 (1)A[i]==B[j]时 F[ ...

  3. 最长公共上升子序列(codevs 2185)

    题目描述 Description 熊大妈的奶牛在小沐沐的熏陶下开始研究信息题目.小沐沐先让奶牛研究了最长上升子序列,再让他们研究了最长公共子序列,现在又让他们要研究最长公共上升子序列了. 小沐沐说,对 ...

  4. codevs 2185 最长公共上升子序列

    题目链接: codevs 2185 最长公共上升子序列codevs 1408 最长公共子序列 题目描述 Description熊大妈的奶牛在小沐沐的熏陶下开始研究信息题目.小沐沐先让奶牛研究了最长上升 ...

  5. [codevs2185]最长公共上升子序列

    [codevs2185]最长公共上升子序列 试题描述 熊大妈的奶牛在小沐沐的熏陶下开始研究信息题目.小沐沐先让奶牛研究了最长上升子序列,再让他们研究了最长公共子序列,现在又让他们要研究最长公共上升子序 ...

  6. hdu1423 最长公共上升子序列

    题目传送门 Greatest Common Increasing Subsequence Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: ...

  7. CF10D LCIS 最长公共上升子序列

    题目描述 This problem differs from one which was on the online contest. The sequence a1,a2,...,an a_{1}, ...

  8. 最长公共上升子序列(LCIS)

    最长公共上升子序列慕名而知是两个字符串a,b的最长公共递增序列,不一定非得是连续的.刚开始看到的时候想的是先用求最长公共子序列,然后再从其中找到最长递增子序列,可是仔细想一想觉得这样有点不妥,然后从网 ...

  9. ZOJ 2432 Greatest Common Increasing Subsequence(最长公共上升子序列+路径打印)

    Greatest Common Increasing Subsequence 题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problem ...

随机推荐

  1. 持续化运维 DevOps

            DevOps(Development和Operations的组合词)是一组过程.方法与系统的统称,用于促进开发(应用程序/软件工程).技术运营和质量保障(QA)部门之间的沟通.协作与整 ...

  2. tomcat 日志

    1.Tomcat的日志(./tomca/logs/) 分为5类,这里面 1和5比较重要 .catalina.--.log 或者 catalina.out: 引擎的日志文件 .host-manager. ...

  3. 浅谈单利模式及其应用场景(Python)

    python 中的单利模式 使用场景: + Python的logger就是一个单例模式,用以日志记录 + Windows的资源管理器是一个单例模式 + 线程池,数据库连接池等资源池一般也用单例模式 + ...

  4. 在Unity中使用 luajit 64位加密

    参考:https://blog.csdn.net/sun19880421/article/details/68070696 https://blog.csdn.net/mydreamremindme/ ...

  5. git的使用方法大全

    换了一个新的工作环境,由于以前都是使用SVN管理代码,现在要换成git,但我对git了解不多,只好下功夫咯!脑子不灵活,命令语句容易忘,所以做个笔记记录下~~~1.安装git到Git官网下载合适自己电 ...

  6. MySQL索引优化深入

    创建 test 测试表 CREATE TABLE `test` (  `id` int(11) NOT NULL AUTO_INCREMENT,  `c1` varchar(10) DEFAULT N ...

  7. AB实验人群定向HTE模型5 - Meta Learner

    Meta Learner和之前介绍的Casual Tree直接估计模型不同,属于间接估计模型的一种.它并不直接对treatment effect进行建模,而是通过对response effect(ta ...

  8. uniapp-使用心得

    <view class="cu-item flex-sub" :class="index==TabCur?'text-orange cur':''" v- ...

  9. pycharm中新建Vue项目时没有vue.js的解决办法

    可能很多小伙伴在使用pycharm 1,新建vue项目的时候并没有发现vue.js的名字, 2,新建.vue文件(即单文件组件)的时候没有 下面就来帮助大家一下,仅供参考 如图: 1.首先我们打开设置 ...

  10. 【WPF学习】第十七章 鼠标输入

    鼠标事件执行几个关联的任务.当鼠标移到某个元素上时,可通过最基本的鼠标事件进行响应.这些事件是MouseEnter(当鼠标指针移到元素上时引发该事件)和MouseLeave(当鼠标指针离开元素时引发该 ...