题解【AcWing272】最长公共上升子序列
一道线性 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】最长公共上升子序列的更多相关文章
- Acwing272 最长公共上升子序列
题目大意:给定两个大小为n的数组,让你找出最长公共上升子序列的长度. 分析:这是一个比较好的dp题,LIS和LCS两大经典线性dp问题相结合,简称LCIS. 代码(O(n*n*n)写法): #incl ...
- CH5101 LCIS(最长公共上升子序列) 题解
每日一题 day16 打卡 Analysis 设F[i,j]表示A[1..i]与B[1..j]并且以B[j]结尾的两段最长公共上升子序列,那么我们可以发现这样的转移 (1)A[i]==B[j]时 F[ ...
- 最长公共上升子序列(codevs 2185)
题目描述 Description 熊大妈的奶牛在小沐沐的熏陶下开始研究信息题目.小沐沐先让奶牛研究了最长上升子序列,再让他们研究了最长公共子序列,现在又让他们要研究最长公共上升子序列了. 小沐沐说,对 ...
- codevs 2185 最长公共上升子序列
题目链接: codevs 2185 最长公共上升子序列codevs 1408 最长公共子序列 题目描述 Description熊大妈的奶牛在小沐沐的熏陶下开始研究信息题目.小沐沐先让奶牛研究了最长上升 ...
- [codevs2185]最长公共上升子序列
[codevs2185]最长公共上升子序列 试题描述 熊大妈的奶牛在小沐沐的熏陶下开始研究信息题目.小沐沐先让奶牛研究了最长上升子序列,再让他们研究了最长公共子序列,现在又让他们要研究最长公共上升子序 ...
- hdu1423 最长公共上升子序列
题目传送门 Greatest Common Increasing Subsequence Time Limit: 2000/1000 MS (Java/Others) Memory Limit: ...
- CF10D LCIS 最长公共上升子序列
题目描述 This problem differs from one which was on the online contest. The sequence a1,a2,...,an a_{1}, ...
- 最长公共上升子序列(LCIS)
最长公共上升子序列慕名而知是两个字符串a,b的最长公共递增序列,不一定非得是连续的.刚开始看到的时候想的是先用求最长公共子序列,然后再从其中找到最长递增子序列,可是仔细想一想觉得这样有点不妥,然后从网 ...
- ZOJ 2432 Greatest Common Increasing Subsequence(最长公共上升子序列+路径打印)
Greatest Common Increasing Subsequence 题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problem ...
随机推荐
- 持续化运维 DevOps
DevOps(Development和Operations的组合词)是一组过程.方法与系统的统称,用于促进开发(应用程序/软件工程).技术运营和质量保障(QA)部门之间的沟通.协作与整 ...
- tomcat 日志
1.Tomcat的日志(./tomca/logs/) 分为5类,这里面 1和5比较重要 .catalina.--.log 或者 catalina.out: 引擎的日志文件 .host-manager. ...
- 浅谈单利模式及其应用场景(Python)
python 中的单利模式 使用场景: + Python的logger就是一个单例模式,用以日志记录 + Windows的资源管理器是一个单例模式 + 线程池,数据库连接池等资源池一般也用单例模式 + ...
- 在Unity中使用 luajit 64位加密
参考:https://blog.csdn.net/sun19880421/article/details/68070696 https://blog.csdn.net/mydreamremindme/ ...
- git的使用方法大全
换了一个新的工作环境,由于以前都是使用SVN管理代码,现在要换成git,但我对git了解不多,只好下功夫咯!脑子不灵活,命令语句容易忘,所以做个笔记记录下~~~1.安装git到Git官网下载合适自己电 ...
- MySQL索引优化深入
创建 test 测试表 CREATE TABLE `test` ( `id` int(11) NOT NULL AUTO_INCREMENT, `c1` varchar(10) DEFAULT N ...
- AB实验人群定向HTE模型5 - Meta Learner
Meta Learner和之前介绍的Casual Tree直接估计模型不同,属于间接估计模型的一种.它并不直接对treatment effect进行建模,而是通过对response effect(ta ...
- uniapp-使用心得
<view class="cu-item flex-sub" :class="index==TabCur?'text-orange cur':''" v- ...
- pycharm中新建Vue项目时没有vue.js的解决办法
可能很多小伙伴在使用pycharm 1,新建vue项目的时候并没有发现vue.js的名字, 2,新建.vue文件(即单文件组件)的时候没有 下面就来帮助大家一下,仅供参考 如图: 1.首先我们打开设置 ...
- 【WPF学习】第十七章 鼠标输入
鼠标事件执行几个关联的任务.当鼠标移到某个元素上时,可通过最基本的鼠标事件进行响应.这些事件是MouseEnter(当鼠标指针移到元素上时引发该事件)和MouseLeave(当鼠标指针离开元素时引发该 ...