首页 > 其他分享 >(CF 10D)最长公共上升子序列(LCIS)(要求输出序列) - 题解

(CF 10D)最长公共上升子序列(LCIS)(要求输出序列) - 题解

时间:2024-08-14 15:28:08浏览次数:11  
标签:pre 输出 LCIS int 题解 ans 序列 赋值

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

原题链接:CodeForces洛谷

时间限制:C/C++ 1000MS,其他语言 2000MS
内存限制:C/C++ 256MB,其他语言 512MB

描述

给定两个整数序列,写一个程序求它们的最长上升公共子序列。
当以下条件满足的时候,我们将长度 \(N\) 的序列 \(S_1,S_2,...,S_N\) 称为长度为 \(M\) 的序列 \(A_1,A_2,...,A_M\) 的上升子序列:
存在 \(1≤i_1<i_2<...<i_N≤M\),使得对所有 \(1≤j≤N\),均有 \(S_j=A_{i_j}\),且对于所有的 \(1≤j<N\),均有 \(S_j<S_{j+1}\)。

输入描述

每个序列用两行表示,
第一行是长度 \(M(1≤M≤500)\)
第二行是该序列的 \(M\) 个整数 \(A_i(−2^{31}<A_i<2^{31})\)

输出描述

在第一行,输出两个序列的最长上升公共子序列的长度 \(L\)。
在第二行,输出该子序列。
如果有不止一个符合条件的子序列,则输出任何一个即可。

用例输入 1

5
1 4 2 5 -12
4
-12 1 2 4

用例输出 1

2
1 4

提示

\(1≤M≤500\)
\(−2^{31}<A_i<2^{31}\)

解析

如何求 LCIS 的长度可以参考 AcWing题解,这里只讲怎么求取并输出这个序列。

用一个 pair<int,int> 的二维数组 \(pre_{i,j}=\{x,y\}\) 来记录 \(f_{i,j}\) 由哪一个 \(f_{x,y}\) 更新而来,最后找到使 \(f_{n,ans}\) 最大的 \(ans\) 以后顺着 \(pre_{n,ans}\) 一路递归回去就可以找到更新出这个最大值的全部路径。

在每次更新 \(f_{i,j}\) 的时候同时更新 \(pre_{i,j}\)。

(此处不算错误但是冗余的想法)

因为在 \(a_i=b_j\) 的时候也可以不加上 \(a_i\),所以在进入 \(k\) 的循环之前还需要将 \(f_{i,j}\) 赋值为 \(f_{i-1,j}\),\(pre_{i,j}\) 也同步赋值为 \(pre_{i-1,j}\),当然如果 \(f_{i-1,j}\) 还没有 \(1\) 大,则可以只把 \(f_{i,j}\) 赋为 \(1\)。

但是 \(f_{i-1,j}\) 由 \(f_{i-2,l},l \in [1,j-1]\) 更新而并 \(+1\),且必须保证 \(b_j>b_l\);当扫描 \(f_{i-1,k},k \in [1,j-1]\) 的时候,因为其已经包含了 \(f_{i-2,j-1}\)(因为 \(f\) 的第一维表示“前 \(i\) 个”),所以它 \(+1\) 以后答案不会小于 \(f_{i-1,j}\)。由此,将 \(f_{i,j}\) 赋值为 \(f_{i-1,j}\) 后不会得到更优解,只用在进入循环前把 \(f_{i,j}\) 赋值为 \(1\) 即可

(当然你将 \(f_{i,j}\) 赋值为 \(f_{i-1,j}\) 了也没问题,在某些情况下(例如用 \(pre_{f_{i-1,k},j}\) 来表示前继时)反而必须用上面先赋为 \(f_{i-1,j}\) 的写法来避免出现同一个 \(pre\) 被多次更新导致指向错误的情况发生,但是用 \(pre_{i,j}\) 来表示就完全不可能产生奇奇妙妙的多次更新错误)。

注意,因为 \(f_{i,j}\) 表示的是“\(a_{1 \sim i},b_{1 \sim j}\) 且以 \(b_j\) 结尾的最长公共上升子序列长度”,并没有要求一定以 \(a_i\) 结尾,所以输出的时候不能输出 a[pre[i][j].first],但因为保证一定以 \(b_j\) 结尾,所以可以输出 b[pre[i][j].second]

代码

注释掉的即为上面说的冗余想法

#include<cstdio>
#include<algorithm>
using namespace std;

const int N=505;
int n,m,a[N],b[N];
int f[N][N];
pair<int,int> pre[N][N];

void DFS(pair<int,int> x)
{
	if(x.first&&x.second)
	{
		DFS(pre[x.first][x.second]);
		printf("%d ",b[x.second]);
	}
	return;
}

int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
		scanf("%d",&a[i]);
	scanf("%d",&m);
	for(int i=1;i<=m;i++)
		scanf("%d",&b[i]);
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
		{
			if(a[i]==b[j])
			{
//				if(f[i-1][j]>1) f[i][j]=f[i-1][j],pre[i][j]=pre[i-1][j];
//				else f[i][j]=1;
				f[i][j]=1;
				for(int k=0;k<j;k++)
					if(b[k]<a[i])
					{
						if(f[i-1][k]+1>f[i][j])
						{
							f[i][j]=f[i-1][k]+1;
							pre[i][j]={i-1,k};
						}
					}
			}
			else
			{
				f[i][j]=f[i-1][j];
				pre[i][j]=pre[i-1][j];
			}
		}
	int ans=0;
	for(int i=1;i<=m;i++)
		if(f[n][i]>f[n][ans]) ans=i;
	printf("%d\n",f[n][ans]);
	DFS({n,ans});
	return 0;
}

标签:pre,输出,LCIS,int,题解,ans,序列,赋值
From: https://www.cnblogs.com/jerrycyx/p/18359042

相关文章

  • 百万级超长序列大模型训练如何加速,硬核解读MindSpeed方案
    摘要:针对现有长序列训练场景的痛点,MindSpeed在并行算法、计算效率、内存占用以及通信四个维度系统性优化大模型长序列训练效率,支持大模型百万级长序列训练。1      长序列已经成为主流大模型能力之一23年底Gemini1.5Pro发布以来,大模型序列长度迅速增长,处理超长序列上下......
  • 【题解】CF1942C1 Bessie's Birthday Cake (Easy Version)
    \(\mathfrak{1st.\Preamble\|}\)前言题目传送门:CF1942C1Bessie'sBirthdayCake(EasyVersion)。蒟蒻在洛谷上第一篇通过的题解。\(\mathfrak{2nd.\Reasoning\|}\)思路其实只需要把选中的点组成一个新的多边形,然后我们就可以发现有\(x\)个点的多边形可以连出\(x-2......
  • 【知识】并查集的单点删除 &【题解】SP5150
    \(\mathfrak{1st.}\)前言-->题目传送门<--原先这道题的难度是紫,我觉得题目翻译看不懂,就去讨论版发了个贴,然后题管更新了题目翻译,并且把难度降到了蓝……\(\mathfrak{2nd.}\)思路赶时间或嫌啰嗦的可以直接跳到『思路归纳』。我们先从普通并查集开始思考对于删除单点\(x\),......
  • 【问题解决】git status中文文件名乱码
    问题复现解决办法在gitbash中直接执行如下命令gitconfig--globalcore.quotepathfalse原因通过gitconfig--help可以查看到以下内容:core.quotePathCommandsthatoutputpaths(e.g.ls-files,diff),willquote"unusual"charactersinthepathnamebyencl......
  • 启动应用程序出现PCLXL.DLL找不到问题解决
    其实很多用户玩单机游戏或者安装软件的时候就出现过这种问题,如果是新手第一时间会认为是软件或游戏出错了,其实并不是这样,其主要原因就是你电脑系统的该dll文件丢失了或没有安装一些系统软件平台所需要的动态链接库,这时你可以下载这个PCLXL.DLL文件(挑选合适的版本文件)把它放入......
  • 项目推荐——音频标注wavesurfer.js用法及相关问题解决
    一、前言上期推荐了文本标注poplar-annotation用法,这期针对音视频标注推荐wavesurfer.js库;Wavesurfer.js是一个基于WebAudioAPI和HTML5Canvas的开源音频可视化库,用于创建可交互、可定制的波形。同时拥有众多插件库。二、demo效果可以实现音视频播放暂停、指定区域......
  • SCI一区级 | Matlab实现INFO-CNN-LSTM-Multihead-Attention多变量时间序列预测
    SCI一区级|Matlab实现INFO-CNN-LSTM-Multihead-Attention多变量时间序列预测目录SCI一区级|Matlab实现INFO-CNN-LSTM-Multihead-Attention多变量时间序列预测效果一览基本介绍程序设计参考资料效果一览基本介绍1.Matlab实现INFO-CNN-LSTM-Multihead-At......
  • (算法)最⻓递增⼦序列————<暴搜->记忆化搜索->动态规划>
    1.题⽬链接:300.最⻓递增⼦序列2.题⽬描述:3.解法(暴搜->记忆化搜索->动态规划):算法思路:暴搜:a.递归含义:给dfs⼀个使命,给他⼀个数i,返回以i位置为起点的最⻓递增⼦序列的⻓度;b.函数体:遍历i后⾯的所有位置,看看谁能加到i这个元素的后⾯。统计所有情况下的最⼤值。......
  • 【实践问题】UART通信问题解决过程
    近期开发了一项通过UART进行读写操作的功能。说起来并不难,但是实际操作起来还是遇到了不少问题,解决问题也费了一番周折。因此记录下来作为积累,也供遇到类似问题的同学参考。问题背景当前的项目需要开发一项功能:BMC通过UART串口与另一设备通信,进行读写操作。听起来并不难,......
  • SciTech-BigDataAIML-LLM-Transformer Series系列: Word Embedding词嵌入详解: 用Corp
    SciTech-BigDataAIML-LLM-TransformerSeries系列:WordEmbedding词嵌入详解:1.用Corpus预训练出嵌入矩阵\(\largeE\)CorpusCollecting:非常重要的工作先收集一个常用的Corpus(语料库),能保障大多数的word都在corpus.有两个特别重要的作用:VocabularyExtracting:词......