BZOJ1264 [AHOI2006]基因匹配Match 动态规划 树状数组
Posted tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ1264 [AHOI2006]基因匹配Match 动态规划 树状数组相关的知识,希望对你有一定的参考价值。
欢迎访问~原文出处——博客园-zhouzhendong
去博客园看该题解
题目传送门 - BZOJ1264
题意概括
给出两个长度为5*n的序列,每个序列中,有1~n各5个。
求其最长公共子序列长度。
题解
我们发现这题的序列特殊性是关键!
我们只需要知道每一种数字在某一个序列中的5个位置,然后对于普通的LCS问题,我们只有在a[i] = b[j]的时候才会+1。
那么我们可以维护一个树状数组,在a序列中,我们一个一个位置扫过去,每次通过树状数组维护的前缀最大值来更新,然后因为修改不多,所以维护最大值是可以的。
这样,修改logn,查询logn,可以承受了。
代码
#include <cstring> #include <algorithm> #include <cstdio> #include <cmath> #include <cstdlib> #include <vector> using namespace std; const int N=20000+5,M=N*5; int n,m,a[M],cnt[N],v[N][5]; int c[M],dp[M]; int lowbit(int x){ return x&-x; } int ask(int x){ int ans=0; for (;x>0;x-=lowbit(x)) ans=max(ans,c[x]); return ans; } void change(int x,int d){ for (;x<=m;x+=lowbit(x)) c[x]=max(c[x],d); } int main(){ scanf("%d",&n); m=n*5; for (int i=1;i<=m;i++) scanf("%d",&a[i]); memset(cnt,0,sizeof cnt); for (int i=1,x;i<=m;i++){ scanf("%d",&x); v[x][cnt[x]++]=i; } memset(c,0,sizeof c); memset(dp,0,sizeof dp); for (int i=1;i<=m;i++) for (int j=4;j>=0;j--){ int pos=v[a[i]][j]; dp[pos]=max(dp[pos],ask(pos-1)+1); change(pos,dp[pos]); } int ans=0; for (int i=1;i<=m;i++) ans=max(ans,dp[i]); printf("%d",ans); return 0; }
以上是关于BZOJ1264 [AHOI2006]基因匹配Match 动态规划 树状数组的主要内容,如果未能解决你的问题,请参考以下文章
BZOJ1264[AHOI2006]基因匹配Match DP+树状数组
BZOJ1264 [AHOI2006]基因匹配Match 动态规划 树状数组