给出 1∼n 的两个排列 P1 和 P2,求它们的最长公共子序列。
输入格式
第一行是一个数 n (1≤n≤10^5)。
接下来两行,每行为 n 个数,为自然数 1∼n 的一个排列。
输出格式
一个数,即最长公共子序列的长度。
样例解释
输入:
5
3 2 1 4 5
1 2 3 4 5
输出:
3
题解:
这里用动态规划会超时,所以就用了个小技巧把问题转换成了求最长上升子序列,然后用二分法就可以了。
#include<iostream>
#include<cstdio>
#define maxn 100003
using namespace std;
int n,x,a[maxn],b[maxn],low[maxn],ans=1;
int main(){
cin>>n;
for(int i=1;i<=n;i++){
scanf("%d",&x);
a[x]=i;
}
for(int i=1;i<=n;i++){
scanf("%d",&x);
b[i]=a[x];
//由此把问题转换为了求最长上升子序列
if(i==1) low[1]=b[1];
else{
//大的往low数组后面加
if(b[i]>low[ans]) low[++ans]=b[i];
//二分法查找
else{
int l=0,r=ans;
while(l<r){
int mid=l+(r-l)/2;
if(low[mid]<b[i]) l=mid+1;
else r=mid;
}
low[l]=b[i];
}
}
}
cout<<ans<<endl;
return 0;
}