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]); }