BZOJ 1264 基因匹配Match(LCS转化LIS)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1264

题意:给出两个数列,每个数列的长度为5n,其中1-n每个数字各出现5次。求两个数列的最长公共子列。

思路:LCS转变为LIS,对于每个在第一个数组中出现的数字,将它转变为在第二个数组里出现的位置,注意这个位置要从大到小排,然后对这个数组做LIS。

#include<algorithm>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
int q[1000005],a[1000005],b[1000005],n,p[1000005],s[100005][6];
int find(int x){
    int l=1,r=q[0],ans;
    if (x<=q[1]) return 0;
    while (l<=r){
        int mid=(l+r)/2;
        if (q[mid]<x) ans=mid,l=mid+1;
        else r=mid-1;
    }
    if (q[ans+1]<x) return ans+1;
    return ans;
}
int main(){
    scanf("%d",&n);
    for (int i=1;i<=5*n;i++) scanf("%d",&a[i]);
    for (int j=1;j<=5*n;j++) scanf("%d",&b[j]);
    for (int i=1;i<=5*n;i++){
        for (int j=1;j<=5;j++)
         if (s[b[i]][j]==0){
                s[b[i]][j]=i;
                break;
         }
    }
    for (int i=1;i<=5*n;i++){
        int t=a[i];
        for (int j=5;j>=1;j--) p[++p[0]]=s[t][j];
    }
    q[0]=1;
    q[1]=p[1];
    for (int i=2;i<=p[0];i++){
        if (p[i]>q[q[0]]) q[++q[0]]=p[i];
        else{
            int t=find(p[i]);
            q[t+1]=p[i];
        }
    } 
    printf("%d\n",q[0]);  
}

 

posted @ 2016-06-02 17:40  GFY  阅读(260)  评论(0编辑  收藏  举报