zoukankan      html  css  js  c++  java
  • bzoj 1264 基因匹配

    Written with StackEdit.

    Description

    卡卡昨天晚上做梦梦见他和可可来到了另外一个星球,这个星球上生物的(DNA)序列由无数种碱基排列而成(地球上只有(4)种),而更奇怪的是,组成(DNA)序列的每一种碱基在该序列中正好出现(5)次!这样如果一个(DNA)序列有(N)种不同的碱基构成,那么它的长度一定是(5N)

    任务:编写一个程序:

    • 从输入文件中读入两个等长的(DNA)序列;
    • 计算它们的最长公共子序列长度;
    • 向输出文件打印你得到的结果。

    Input

    输入文件中第一行有一个整数(N),表示这个星球上某种生物使用了N种不同的碱基,以后将它们编号为(1…N)的整数。

    以下还有两行,每行描述一个(DNA)序列:包含(5N)(1…N)的整数,且每一个整数在对应的序列中正好出现(5)次。

    Output

    输出文件中只有一个整数,即两个(DNA)序列的最长公共子序列长度。

    Sample Input

    2
    1 1 2 2 1 1 2 1 2 2
    1 2 2 2 1 1 2 2 1 1

    Sample Output

    7

    HINT

    [数据约束和评分方法]

    (60\%)的测试数据中:(1<=N <= 1000.)
    (100\%)的测试数据中:(1<=N <= 20000.)

    Solution

    • 朴素的(O(n^2)dp)只能解决(60\%)的部分.
    • 注意到一个关键性质,每个数在每个序列中都恰好出现(5)次.
    • 类似于给两个排列求(LCS),我们可以记录下每个数字在第一个序列(a)中从前往后的(5)个位置.
    • 再处理第二个序列(b),此时我们处理当前数(b[i])在第一个序列中每个出现的位置(pos).有(a[pos]=b[i].)
    • 那么根据朴素(dp)的思路,定义(f[i])为只用(a)序列的前(i)个数的(LCS)长度.
    • 此时就可以完成更新(f[pos]=max(f[1)~(pos-1])+1).利用树状数组维护最大值进行优化.
    • 特别注意:每个(b[i])对应了(5)(pos),而我们处理它们的时候应该从后往前倒序处理,否则先更新的会对后面的造成影响,破坏无后效性(类似01背包).
    #include<bits/stdc++.h>
    #define lowbit(x) x&(-x)
    using namespace std;
    typedef long long LoveLive;
    inline int read()
    {
    	int out=0,fh=1;
    	char jp=getchar();
    	while ((jp>'9'||jp<'0')&&jp!='-')
    		jp=getchar();
    	if (jp=='-')
    		{
    			fh=-1;
    			jp=getchar();
    		}
    	while (jp>='0'&&jp<='9')
    		{
    			out=out*10+jp-'0';
    			jp=getchar();
    		}
    	return out*fh;
    }
    const int MAXN=2e5+10;
    int ta[MAXN];
    int va[MAXN][10];
    int bit[MAXN];
    int n;
    inline void upd(int x,int c)
    {
    	for(;x<=n;x+=lowbit(x))
    		bit[x]=max(bit[x],c);
    }
    inline int query(int x)
    {
    	int res=0;
    	for(;x;x-=lowbit(x))
    		res=max(res,bit[x]);
    	return res;
    }
    int main()
    {
    	n=read();
    	n*=5;
    	for(int i=1;i<=n;++i)
    		{
    			int t=read();
    			va[t][++ta[t]]=i;
    		}
    	for(int i=1;i<=n;++i)
    		{
    			int t=read();
    			for(int j=5;j>=1;--j)//值得细细斟酌
    				{
    					int pos=va[t][j];
    					int mx=query(pos-1)+1;
    					upd(pos,mx);
    				}
    		}
    	int ans=query(n);
    	printf("%d
    ",ans);
    	return 0;
    }
    
    
  • 相关阅读:
    matplotlib数据可视化之柱形图
    xpath排坑记
    Leetcode 100. 相同的树
    Leetcode 173. 二叉搜索树迭代器
    Leetcode 199. 二叉树的右视图
    Leetcode 102. 二叉树的层次遍历
    Leetcode 96. 不同的二叉搜索树
    Leetcode 700. 二叉搜索树中的搜索
    Leetcode 2. Add Two Numbers
    Leetcode 235. Lowest Common Ancestor of a Binary Search Tree
  • 原文地址:https://www.cnblogs.com/jklover/p/10070357.html
Copyright © 2011-2022 走看看