0
点赞
收藏
分享

微信扫一扫

洛谷P1439最长公共子序列

千行 2022-02-17 阅读 31

传送门

最长公共子序列可以考虑转化为最大上升子序列。很容易想到用结构体存储元素i(1<=i<=n)分别在两个序列中出现的位置,按其在第一个序列中出现的位置排序,对样例便有:

此时i在a中出现顺序一定从前往后排列,求最大公共子序列长度只需找到b中最长的上升子序列长度即可。

#include<bits/stdc++.h>
#define ff(i,s,e) for(int i=s;i<=e;i++)
using namespace std;
inline int read(){
    register int x=0,f=1;register char ch=getchar();
    while(ch>'9'||ch<'0'){if(ch=='-') f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    return x*f;
}
const int m=100005;
int n,f[m];
struct qwq{
    int a,b;
}x[m];
bool cmp(qwq x,qwq y){
    return x.a<y.a;
}
int find(int l,int r,int x){//二分在已知上升序列中找第一个大于x的数
    while(l<=r){
        int mid=(l+r)/2;
        if(f[mid]<x) l=mid+1;
        else r=mid-1;
    }
    return l;
}
int main(){
    n=read();
    ff(i,1,n) x[read()].a=i;
    ff(i,1,n) x[read()].b=i;
    sort(x+1,x+n+1,cmp);
    int len=0;
    ff(i,1,n){
        if(x[i].b>f[len])//若大于当前最大上升子序列最大元素,存储
            f[++len]=x[i].b;
        else{f[find(1,len,x[i].b)]=x[i].b;}//用x替换大于x的数,保证后面解最优
    }
    printf("%d",len);
    return 0;
}

看下数据,n最大可以达到1e5,显然普通dp的O(n2)求法会爆,便能想到二分。

举报

相关推荐

0 条评论