CF10D-LCIS题解--线性DP+打印方案
题目链接:
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+打印方案的更多相关文章
- CF10D LCIS(线性DP)
题意:\(LCIS\)输出方案 变迁の时刻,标记它 P.S:特判没\(LCIS\)的情况 //#include <iostream> #include <cstdio> #in ...
- HDU2929 Bigger is Better[DP 打印方案 !]
Bigger is Better Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others ...
- BestCoder Round #87 1002 Square Distance[DP 打印方案]
Square Distance Accepts: 73 Submissions: 598 Time Limit: 4000/2000 MS (Java/Others) Memory Limit ...
- CH5101 LCIS【线性dp】
5101 LCIS 0x50「动态规划」例题 描述 熊大妈的奶牛在小沐沐的熏陶下开始研究信息题目.小沐沐先让奶牛研究了最长上升子序列,再让他们研究了最长公共子序列,现在又让他们研究最长公共上升子序列了 ...
- HDU 2296 Ring [AC自动机 DP 打印方案]
Ring Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submissio ...
- 【题解】POJ1934 Trip (DP+记录方案)
[题解]POJ1934 Trip (DP+记录方案) 题意: 传送门 刚开始我是这么设状态的(谁叫我DP没学好) \(dp(i,j)\)表示钦定选择\(i\)和\(j\)的LCS,然而你会发现这样钦定 ...
- 线性DP总结(LIS,LCS,LCIS,最长子段和)
做了一段时间的线性dp的题目是时候做一个总结 线性动态规划无非就是在一个数组上搞嘛, 首先看一个最简单的问题: 一,最长字段和 下面为状态转移方程 for(int i=2;i<=n;i++) { ...
- Codeforces 176B (线性DP+字符串)
题目链接: http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=28214 题目大意:源串有如下变形:每次将串切为两半,位置颠倒形成 ...
- 线性dp
线性dp应该是dp中比较简单的一类,不过也有难的.(矩乘优化递推请出门右转) 线性dp一般是用前面的状态去推后面的,也有用后面往前面推的,这时候把循环顺序倒一倒就行了.如果有的题又要从前往后推又要从后 ...
随机推荐
- react 实现数据双向绑定
好久没有更新了 只是都写在有道笔记中 今天整理下 一些基础的 大神勿喷 一个基础的不能再基础的数据双向绑定 因为react不同于vue 没有v-model指令 所以怎么实现呢? import Reac ...
- 问题解决:fatal error C1083: 无法打开包括文件:No such file or directory
fatal error C1083: 无法打开包括文件:No such file or directory将别的工程直接用VS2010打开出现了该问题,此时必须检查是不是: 1. 如果要引入的这些.h ...
- wpf相关好资源
Textbox Drag/Drop in WPFhttp://www.codeproject.com/Articles/42696/Textbox-Drag-Drop-in-WPF.aspx Odys ...
- 线程池小结(JDK8)
1.线程池的好处 降低资源消耗(重复利用已创建的线程减少创建和销毁线程的开销) 提高响应速度(无须创建线程) 提高线程的可管理性 2.相关类图 JDK5以后将工作单元和执行机制分离开来,工作单元包括R ...
- 7. grep
grep命令 grep grep是通用正则表达式分析程序(General Regular Expression Parser)的缩写. grep命令可以在它的输入中搜索指定的字符串模式(Pattern ...
- 【Java】生成随机的手机号码并输出到文件
import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.util.R ...
- python基础知识(集合)
集合 可变集合set()/不可变集合frozenset() {} 大写的拉丁字母 用于保存不重复元素.无序不能通过索引来获取 集合的创建 空集合 使用set()函数 变量名 = set() 集合的添 ...
- springboot使用elasticsearch的客户端操作eslaticsearch
一 ES客户端 ES提供多种不同的客户端: 1.TransportClient ES提供的传统客户端,官方计划8.0版本删除此客户端. 2.RestClient RestClient是官方推荐使用的 ...
- element-ui--按需引入
参考链接:https://www.cnblogs.com/qiezuimh/p/10103522.html
- Apache——开启个人用户主页功能
个人主页功能分为不加密和加密两种 不加密: 先来建立几个用户,我这是建了两个 例:命令为:useradd qiyuan 然后输入:passwd qiyuan,改一下密码 我们看一下家目录下面: 已经 ...