您的位置:首页 > 其它

洛谷P1439 最长公共子序列(LCS问题)

2017-11-01 15:31 281 查看

DP

题目传送门

一般LCS做法是O(n2)的,但是这道题数据范围有1e5,因此必须另辟蹊径

注意到两个数列是n的一个排列,因此考虑把第一个数列中数的位置给记录下来,再根据这个记录第二个数列的位置。然后就转化成了LIS问题,用O(nlog2n)来实现即可。

讲的不是很清楚啊。。。具体看代码吧。。。

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#define MAXN 100000
using namespace std;
int n,t;
int g[MAXN+5],f[MAXN+5],a[MAXN+5],b[MAXN+5],c[MAXN+5];
inline char readc(){
static char buf[100000],*l=buf,*r=buf;
if (l==r) r=(l=buf)+fread(buf,1,100000,stdin);
if (l==r) return EOF; return *l++;
}
inline int _read(){
int num=0; char ch=readc();
while (ch<'0'||ch>'9') ch=readc();
while (ch>='0'&&ch<='9') { num=num*10+ch-48; ch=readc(); }
return num;
}
int erfen(int v){
int l=1,r=t;
while (l<=r){
int mid=(l+r)/2;
if (v>g[mid]) l=mid+1;
else r=mid-1;
}
return l;
}
int main(){
n=_read();
for (int i=1;i<=n;i++) a[i]=_read(),f[a[i]]=i;//记录位置
for (int i=1;i<=n;i++) b[i]=_read(),c[i]=f[b[i]];//根据上次的记录来记录
g[++t]=c[1];
for (int i=2;i<=n;i++)//LIS
if (c[i]>g[t]) g[++t]=c[i];
else g[erfen(c[i])]=c[i];
printf("%d\n",t);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: