题目描述

给出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


【分析】
一个好的题解比那些冗长的题解不知道好到哪里去
借鉴洛谷题解
首先简化一下问题,假设P1恰好为单调递增的1,2,3,…n,那么很显然答案就是P2的最长上升子序列的长度(想一想,为什么?)

问题是P1并非单调递增的,但我们可以假定它就是1,2,3,…,n,将P1[1]映射到1,P1[2]映射到2,……然后再将P2作相同的变换即可,这样只要求P2的最长上升子序列了。

不会LIS(最长上升子序列)算法的请自行百度…


【代码】

//P1439 排列LCS问题
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
#define M(a) memset(a,0,sizeof a)
#define fo(i,j,k) for(i=j;i<=k;i++)
using namespace std;
const int mxn=100005;
int a[mxn],mp[mxn],d[mxn];
int n,len;
int main()
{
int i,j,x;
scanf("%d",&n);
fo(i,1,n)
{
scanf("%d",&x);
mp[x]=i;
}
fo(i,1,n)
{
scanf("%d",&x);
a[i]=mp[x];
}
d[len=1]=a[1];
fo(i,2,n)
{
if(a[i]<d[1]) d[1]=a[i];
else if(a[i]>d[len]) d[++len]=a[i];
else d[lower_bound(d+1,d+len+1,a[i])-d]=a[i];
}
printf("%d\n",len);
return 0;
}