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+树状数组

BZOJ 1264 [AHOI2006]基因匹配Match

bzoj1264: [AHOI2006]基因匹配Match

BZOJ1264 [AHOI2006]基因匹配Match 动态规划 树状数组

bzoj 1264: [AHOI2006]基因匹配Match (树状数组优化dp)

[BZOJ1264][AHOI2006]基因匹配Match(DP + 树状数组)