Luogu 1439 【模板】最长公共子序列

题目描述

给出1-n的两个排列P1和P2,求它们的最长公共子序列。

输入输出格式

输入格式:

第一行是一个数n,

接下来两行,每行为n个数,为自然数1-n的一个排列。

输出格式:

一个数,即最长公共子序列的长度

输入输出样例

输入样例#1:

5
3 2 1 4 5
1 2 3 4 5

输出样例#1:

3

说明

【数据规模】

对于50%的数据,n≤1000

对于100%的数据,n≤100000

【题解】

首先不难想到的是将其转化成一个序列的最长上升子序列

由于两个序列均为1~n的排列,在将其中一个序列的元素换成该元素在另一序列中的下标时,最长公共子序列即可写成一个最长上升子序列,其中每一项的值为在其中一个序列中的下标(由观察样例不难发现 因为样例给了一个序列为1 2 3 4 5,替换的想法较为明显)

然后就可以二分地做到O(nlogn)

 1 //luogu P1439
 2 int n;
 3 int a[111111],b[111111];
 4 int dy[111111];
 5 int f[111111];
 6 int ans;
 7
 8 int main(){
 9     n=read();
10     for(int i=1;i<=n;i++) a[i]=read(),dy[a[i]]=i;
11     for(int i=1;i<=n;i++) b[i]=read(),b[i]=dy[b[i]];
12
13     for(int i=1;i<=n;i++){
14         if(b[i]>f[ans]){
15             ans++;
16             f[ans]=b[i];
17         }
18         else{
19             f[lower_bound(f+1,f+ans+1,b[i])-f]=b[i];
20         }
21     }
22
23     print(ans);
24     return 0;
25 }

时间: 2024-10-07 02:02:06

Luogu 1439 【模板】最长公共子序列的相关文章

模板 最长公共子序列

[模板]最长公共子序列 1 #include <stdio.h> 2 #include <string.h> 3 #include <algorithm> 4 using namespace std; 5 6 char s1[1000],s2[1000]; 7 int len1,len2,dp[1000][1000],mark[1000][1000];//如果数据太大,dp数组可以考虑滚动数组 8 9 void LCS() 10 { 11 int i,j; 12 mem

【Luogu】P3402最长公共子序列(LCS-&gt;nlognLIS)

题目链接 SovietPower 的题解讲的很清楚.Map或Hash映射后用nlogn求出LIS.这里只给出代码. #include<cstdio> #include<cctype> #include<map> #include<algorithm> using namespace std; map<int,int> vis; inline long long read(){ long long num=0,f=1; char ch=getcha

【luogu 1439 最长公共子序列】

题目描述 给出1-n的两个排列P1和P2,求它们的最长公共子序列. 输入输出格式 输入格式: 第一行是一个数n, 接下来两行,每行为n个数,为自然数1-n的一个排列. 输出格式: 一个数,即最长公共子序列的长度 输入输出样例 输入样例#1: 复制 5 3 2 1 4 5 1 2 3 4 5 输出样例#1: 复制 3 说明 [数据规模] 对于50%的数据,n≤1000 对于100%的数据,n≤100000 [题解]       ①LCS->LIS       ②树状数组维护nlogn LIS #i

最长公共子序列(luogu 1439)

题目描述 给出1-n的两个排列P1和P2,求它们的最长公共子序列. 输入输出格式 输入格式: 第一行是一个数n, 接下来两行,每行为n个数,为自然数1-n的一个排列. 输出格式: 一个数,即最长公共子序列的长度 输入输出样例 输入样例 5 3 2 1 4 5 1 2 3 4 5 输出样例 3 说明 [数据规模] 对于50%的数据,n≤1000 对于100%的数据,n≤100000 瞬时记忆 O(nlogn) 做法,意思大概是先把一个 a 序列映射到一个数组(似乎是叫做离散化),然后用它-- 代码

【luogu1439】 【模板】最长公共子序列 [动态规划][LIS最长上升子序列][离散化]

P1439 [模板]最长公共子序列 此思路详见luogu第一个题解 一个很妙的离散化 刘汝佳蓝书上面的LIS 详见蓝书 d[i]以i为结尾的最长上升子序列的长度     g[i]表示d值为i的最小状态的编号即长度为i的上升子序列的最小末尾值 1 for(int i=1;i<=n;++i) scanf("%d",&a[i]); 2 for(int i=1;i<=n;++i) 3 { 4 int k=lower_bound(g+1,g+1+n,a[i])-g; 5 d[

【模板】最长公共子序列(二维偏序)

给出1-n的两个排列P1和P2,求它们的最长公共子序列. 洛谷1439 1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 const int maxn=100010; 5 int n,x,ans,tmp,pos[maxn],t[maxn]; 6 void read(int &k){ 7 k=0; int f=1; char c=getchar(); 8 while(c<'0'||c>

洛谷 P1439 【模板】最长公共子序列

神TM模板..我本来想休闲一下写点水题的... 开始做的时候直接敲了一个O(N2)的算法上去,编译的时候才发现根本开不下.. 好了,谈回这道题. 先不加证明的给出一种算法. 若有一组数据 2 4 2 5 1 3 2 5 4 1 3 那么我们令 4 2 5 1 3 | | | | | 1 2 3 4 5 第三行的数据就变成 2 3 1 4 5 很明显,答案是这个数据的最长上升子序列,即4 == 2 3 4 5,即原数列的2 5 1 3. 现在来大概的介绍一下这样做的原因. 首先,观察题目,注意到这

luogu P3402 最长公共子序列

题目背景 DJL为了避免成为一只咸鱼,来找Johann学习怎么求最长公共子序列. 题目描述 经过长时间的摸索和练习,DJL终于学会了怎么求LCS.Johann感觉DJL孺子可教,就给他布置了一个课后作业: 给定两个长度分别为n和m的序列,序列中的每个元素都是正整数.保证每个序列中的各个元素互不相同.求这两个序列的最长公共子序列的长度. DJL最讨厌重复劳动,所以不想做那些做过的题.于是他找你来帮他做作业. 输入输出格式 输入格式: 第一行两个整数n和m,表示两个数列的长度. 第二行一行n个整数a

51Nod - 1006 最长公共子序列Lcs模板

给出两个字符串A B,求A与B的最长公共子序列(子序列不要求是连续的). 比如两个串为: abcicba abdkscab ab是两个串的子序列,abc也是,abca也是,其中abca是这两个字符串最长的子序列. Input 第1行:字符串A 第2行:字符串B (A,B的长度 <= 1000)Output输出最长的子序列,如果有多个,随意输出1个. Sample Input abcicba abdkscab Sample Output abca 只能求最长公共子序列的长度,不能输出这个串是什么