题目链接:

https://www.luogu.org/problemnew/show/CF10D

方法一

分析

\(LCS\)和\(LIS\)已经成烂大街的知识了,可是当这两个合并起来成为\(LCIS\),解决的方式方法也多了起来.

首先有种最朴素的\(O(N^4)\)方法,\(f[i][j]\)表示A串第\(i\)个字母和B串第\(j\)个字母结尾的状态中\(LCIS\)的长度,那么

那么如果\(a[i]==b[j],f[i][j]=max_{0<=k<j且b[k]<a[i](b[j])}(f[i-1][k])+1\)

否则\(f[i][j]=f[i-1][j]\)

但是这种方法怎么打印方案呢?我们用\(path[j][len[j]]\)表示以\(j\)结尾的\(LCIS\)方案,\(len[j]\)指的是以\(j\)结尾的\(LCIS\)长度

这样我们从\(k\)更新到\(j\)时,首先将\(path[k][len[k]]\)全部复制到\(path[j][len[j]]\);

然后\(len[j]=len[k]+1,path[j][len[j]]=b[j]\)

跑时950+ms

代码

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cctype>
#include <queue>
#include <vector>
#define ll long long
#define ri register int
using std::max;
using std::min;
using std::swap;
template <class T>inline void read(T &x){
x=0;int ne=0;char c;
while(!isdigit(c=getchar()))ne=c=='-';
x=c-48;
while(isdigit(c=getchar()))x=(x<<3)+(x<<1)+c-48;
x=ne?-x:x;return ;
}
const int maxn=505;
const int inf=0x7fffffff;
int n,m,a[maxn],b[maxn],f[maxn][maxn],len[maxn];
int path[maxn][maxn];
void print(int x){
for(ri i=1;i<=len[x];i++)printf("%d ",path[x][i]);
puts("");
return ;
}
int main(){
int x,y,z;
int ans=-inf,ed=0;
read(n);
for(ri i=1;i<=n;i++){read(a[i]);}
read(m);
for(ri i=1;i<=m;i++){read(b[i]);}
a[0]=b[0]=-inf;
for(ri i=1;i<=n;i++){
for(ri j=1;j<=m;j++){
if(a[i]==b[j]){
for(ri k=0;k<j;k++){
if(b[k]<a[i]){
//f[i][j]=max(f[i][j],f[i-1][k]+1);
if(f[i][j]<f[i-1][k]+1){
f[i][j]=f[i-1][k]+1;
len[j]=len[k]+1;
for(ri p=1;p<=len[k];p++)path[j][p]=path[k][p];
}
}
}
}
else f[i][j]=f[i-1][j];
//ans=max(ans,f[i][j]);
path[j][len[j]]=b[j];
if(ans<f[i][j]){
ans=f[i][j];
ed=j;
}
}
}
printf("%d\n",ans);
print(ed);
return 0;
}

方法二

我们考虑递推时的决策集合,\(f[i][j]\)都是由\(f[i][k](b[k]<a[i])\)递推得到,那么我们如果在从\(f[i][0]\)递推到\(f[i][j]\)时我们已经记录下所有\(f[i][k]\)的最大值设为\(val\),直接将\(f[i][j]\)设为\(max(f[i][j],val+1)\)就好了,打印路径的方法跟方法一类似

这样时间复杂度能少个\(N\)

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <queue>
#include <algorithm>
#define ll long long
#define ri register int
#define ull unsigned long long
using std::min;
using std::max;
using std::swap;
template <class T>inline void read(T &x){
x=0;int ne=0;char c;
while(!isdigit(c=getchar()))ne=c=='-';
x=c-48;
while(isdigit(c=getchar()))x=(x<<3)+(x<<1)+c-48;
x=ne?-x:x;return ;
}
const int maxn=505;
const int inf=0x7ffffff;
int n,m,a[maxn],b[maxn],f[maxn][maxn],path[maxn][maxn],len[maxn],ed;
int main(){
read(n);
for(ri i=1;i<=n;i++){
read(a[i]);
}
read(m);
for(ri i=1;i<=m;i++){
read(b[i]);
}
int ans=-inf,val,lst=0;
for(ri i=1;i<=n;i++){
lst=0;
val=f[i-1][0];
for(ri j=1;j<=m;j++){
if(a[i]==b[j]){
if(val+1>f[i][j]){
f[i][j]=val+1;
for(ri k=1;k<=len[lst];k++)path[j][k]=path[lst][k];
len[j]=len[lst]+1;
}
}
else f[i][j]=f[i-1][j];
path[j][len[j]]=b[j];
//ans=max(ans,f[i][j]);
if(f[i][j]>ans){
ans=f[i][j];
ed=j;
}
if(b[j]<a[i]){
//val=max(val,f[i-1][j]);
if(val<f[i-1][j]){
val=f[i-1][j];
lst=j;
}
}
}
}
printf("%d\n",ans);
//printf("%d %d\n",ed,len[ed]);
for(ri i=1;i<=len[ed];i++)printf("%d ",path[ed][i]);
return 0;
}

当然题解中还有\(O(1)\)记录路径的方法,以及\(O(N)\)的空间复杂度方法,这里先挖个坑吧

CF10D-LCIS题解--线性DP+打印方案的更多相关文章

  1. CF10D LCIS(线性DP)

    题意:\(LCIS\)输出方案 变迁の时刻,标记它 P.S:特判没\(LCIS\)的情况 //#include <iostream> #include <cstdio> #in ...

  2. HDU2929 Bigger is Better[DP 打印方案 !]

    Bigger is Better Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others ...

  3. BestCoder Round #87 1002 Square Distance[DP 打印方案]

    Square Distance  Accepts: 73  Submissions: 598  Time Limit: 4000/2000 MS (Java/Others)  Memory Limit ...

  4. CH5101 LCIS【线性dp】

    5101 LCIS 0x50「动态规划」例题 描述 熊大妈的奶牛在小沐沐的熏陶下开始研究信息题目.小沐沐先让奶牛研究了最长上升子序列,再让他们研究了最长公共子序列,现在又让他们研究最长公共上升子序列了 ...

  5. HDU 2296 Ring [AC自动机 DP 打印方案]

    Ring Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submissio ...

  6. 【题解】POJ1934 Trip (DP+记录方案)

    [题解]POJ1934 Trip (DP+记录方案) 题意: 传送门 刚开始我是这么设状态的(谁叫我DP没学好) \(dp(i,j)\)表示钦定选择\(i\)和\(j\)的LCS,然而你会发现这样钦定 ...

  7. 线性DP总结(LIS,LCS,LCIS,最长子段和)

    做了一段时间的线性dp的题目是时候做一个总结 线性动态规划无非就是在一个数组上搞嘛, 首先看一个最简单的问题: 一,最长字段和 下面为状态转移方程 for(int i=2;i<=n;i++) { ...

  8. Codeforces 176B (线性DP+字符串)

    题目链接: http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=28214 题目大意:源串有如下变形:每次将串切为两半,位置颠倒形成 ...

  9. 线性dp

    线性dp应该是dp中比较简单的一类,不过也有难的.(矩乘优化递推请出门右转) 线性dp一般是用前面的状态去推后面的,也有用后面往前面推的,这时候把循环顺序倒一倒就行了.如果有的题又要从前往后推又要从后 ...

随机推荐

  1. docker安装并设置开机启动(CentOS7/8)

    CentOS7.2 docker分为CE和EE版本,EE版本收费,一般我们使用CE版本就满足要求了 docker安装及启动 docker安装很简单,直接使用如下命令安装即可,安装后的docker版本即 ...

  2. docker进入容器的四种方法

    在使用Docker创建了容器之后,大家比较关心的就是如何进入该容器了,其实进入Docker容器有好几多种方式,这里我们就讲一下常用的几种进入Docker容器的方法. 进入Docker容器比较常见的几种 ...

  3. AVQueuePlayer

    想要视频一个接一个的无缝连续播放么? 还在用mpmovieplayercontroller么?out了! 介绍一个可以实现无缝连续播放视频的东西-------AVQueuePlayer ! AVQue ...

  4. oracle数据ORA-03113:通信通道的文件到达结尾的简单处理方式

    <ORA-03113:通信通道的文件结尾>错误处理: 出现的主要原因是由于归档日志空间不够了. 解决办法: --以sysdba方式登录 sqlplus / as sysdba --关闭数据 ...

  5. router-link跳转页面传递参数及页面刷新方法

    使用router-link传参: 第一种: 路径:http://localhost:8080/goodListP?id=2 跳转的页面获取参数: this.$route.query.id 第二种: 路 ...

  6. Go项目实战:打造高并发日志采集系统(一)

    项目结构 本系列文章意在记录如何搭建一个高可用的日志采集系统,实际项目中会有多个日志文件分布在服务器各个文件夹,这些日志记录了不同的功能.随着业务的增多,日志文件也再增多,企业中常常需要实现一个独立的 ...

  7. Java泛型(7):无界通配符<?>

    无界通配符<?>很容易和原生类型混淆. 以List为例: List表示持有任何Object类型的原生List,其实就等价于List<Object> List<?>表 ...

  8. 用事件队列来处理pixi中的场景元素入场

    在pixi中,添加一个精灵元素,你可能需要,先将贴图load进来,然后才能添加到场景中去,所以一般会这么操作 Loader.add("tree","static/imag ...

  9. bash-2 httpd服务的源码编译安装脚本

    httpd服务的源码编译安装脚本 #!/bin/bash # #******************************************************************** ...

  10. fdisk中参数配置说明表

    命令 描述 a 设置活动分区标志 b 编辑BSD Unix系统用的磁盘标签 c 设置DOS兼容标志 d 删除分区 l 显示可用的分区类型 m 显示命令选项(帮助) n 添加一个新的分区 o 创建DOS ...