zoukankan      html  css  js  c++  java
  • P3402 最长公共子序列(nlogn)

    https://www.luogu.org/problem/show?pid=3402
    这里写图片描述
    先看一下数据规模:n<=300000,n^2的做法肯定就要挂掉了,所以用到了这个nlogn的做法。
    先介绍一下nlogn的做法:
    最长公共子序列 的 nlogn 的算法本质是 将该问题转化成 最长增序列(LIS),因为 LIS 可以用nlogn实现,所以求LCS的时间复杂度降低为 nlogn。
    转化:将LCS问题转化成LIS问题。
    假设有两个序列 s1[ 1~6 ] = { a, b, c , a, d, c }, s2[ 1~7 ] = { c, a, b, e, d, a, b }。
    记录s1中每个元素在s2中出现的位置, 再将位置按降序排列, 则上面的例子可表示为:
    loc( a)= { 6, 2 }, loc( b ) = { 7, 3 }, loc( c ) = { 1 }, loc( d ) = { 5 }。
    将s1中每个元素在s2中的位置按s1中元素的顺序排列成一个序列s3 = { 6, 2, 7, 3, 1, 6, 2, 5, 1 }。
    在对s3求LIS得到的值即为求LCS的答案。
    证明略。

    再观察数据,ai<=10^9,那普通的数组肯定就不行了。然后再看一下题目,每个元素不会重复。所以就产生了两种处理方法:哈希 or map(当然大佬会选择省时的哈希,我就只能去用map了)。
    还要注意一个问题,在对应中,出现位置是0的直接跳过,因为这是没有对应的,肯定不是共有的元素啦。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<vector>
    #include<algorithm>
    #include<map>
    using namespace std;
    map <int,int> ma; 
    int n,m;
    int s1[300009],s2[300009];
    int a[300009],low[300009],len;
    int find(int l,int r,int z)
    {
        int mid;
        while(l<=r)
        {
            int mid=(l+r)>>1;
            if(low[mid]<=z)
             l=mid+1;
            else r=mid-1;
        }
        return l;
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
          scanf("%d",&s1[i]);
        for(int i=1;i<=m;i++)
          scanf("%d",&s2[i]);
        for(int i=1;i<=m;i++)
          ma[s2[i]]=i;
        for(int i=1;i<=n;i++)
          a[i]=ma[s1[i]];
        int t=1;
        while(a[t]==0) t++;
        low[++len]=a[t];
        for(int i=2;i<=n;i++)
        {
            if(a[i]==0) continue;
            if(a[i]>low[len])
             low[++len]=a[i];
            else
             {
                //low[upper_bound(low+1,low+len+1,a[i])-low]=a[i];//自带函数
                low[find(1,len,a[i])]=a[i];//正确的二分 
             }
        }   
        printf("%d",len);
        return 0;    
    }
  • 相关阅读:
    lambda 是个啥玩意
    python中读写操作plist
    通过os中的os.path.basename获取路径中的文件名
    python遍历目录的两种方法
    mac下已有pyhon2.7,装了python3 之后,怎么调用python3啊
    Python: easy_install & pip 下载PyPi 公共资源库的工具
    安装python的图形处理库: pillow
    minSdkVersion, targetSdkVersion, targetApiLevel,compileSdkVersion,buildToolsVersion
    bat 批量修改文件名字
    a b两向量叉乘 <0说明a在b左边
  • 原文地址:https://www.cnblogs.com/dfsac/p/7587921.html
Copyright © 2011-2022 走看看