• 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;
    }
    

      

  • 相关阅读:
    Tensorflow使用环境配置
    学习笔记——EM算法
    学习笔记——提升方法
    学习笔记——支持向量机
    加入BOINC(伯克利开放式网络计算平台)
    斐波那契大数模板
    多重部分和的计数dp
    POJ 2674 Linear world
    POJ 1222 EXTENDED LIGHTS OUT(翻转+二维开关问题)
    POJ3185 The Water Bowls(反转法or dfs 爆搜)
  • 原文地址:https://www.cnblogs.com/zhouzhendong/p/BZOJ1264.html
Copyright © 2020-2023  润新知