洛谷1439 排列LCS问题

洛谷1439 排列LCS问题

本题地址: http://www.luogu.org/problem/show?pid=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 + 二分优化LIS

   首先明确题目的特殊性:序列为1-n的一个排列即一个序列中不存在重复的元素。

   如果LCS正常思路算时间为O(n^2)而且空间需要二维,显然不适用于本题。

   这里将第一个序列a重新编号为1..n,并以这个编号规则重新定义第二个序列b,则问题转化为求新的第二个序列的LIS。

   O(nlogn)求LIS的方法:二分查找。构造一个g数组,g[i]表示d值为i且最小的a值,每次转移求d[i]可以从g中二分查找满足小于a[i]的最大d值,算法在白书上有过探讨(P62)这里不再赘述。

   数据很大,可以考虑优化读入。

 

【代码】

 

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 using namespace std;
 5 
 6 const int maxn = 100000+10;
 7 const int INF=1<<30;
 8 int n;
 9 int a[maxn],b[maxn],d[maxn];
10 
11 inline int read_int() {
12     char c; c=getchar();
13     while(!isdigit(c)) c=getchar();
14     
15     int x=0;
16     while(isdigit(c)) {
17         x=x*10+c-'0';
18         c=getchar();
19     }
20     return x;
21 }
22 
23 int main() {
24     n=read_int();
25     int tmp[maxn];
26     for(int i=1;i<=n;i++) a[i]=read_int() , tmp[a[i]]=i;
27     for(int i=1;i<=n;i++) b[i]=read_int() , b[i]=tmp[b[i]];
28     
29     int g[maxn],ans=0;
30     for(int i=1;i<=n;i++) g[i]=INF;
31     for(int i=1;i<=n;i++) {
32         int k=lower_bound(g+1,g+n+1,b[i])-g;
33         d[i]=k;
34         g[d[i]]=b[i];
35         ans=max(ans,d[i]);  //return max
36     }
37     cout<<ans<<"\n";
38     return 0;
39 }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值