Luogu P1439 【模板】最长公共子序列

  又是模板题呵,但这次的难度有点增加。

  先看题目第一个想到DP的经典算法,要O(n^2),然后想其它的算法。

  其实我们衢州市一次联考有一题很像这题,不过还要难一点。

  思想是离散化+最长不下降子序列(在这里和最长上升子序列等价,因为没有重复的值)

  先离散一下第二串里每个点的第一串里的位置(数组也可以,但我喜欢用map),如样例:

  5 

  3 2 1 4 5
  1 2 3 4 5

  散出来就是 3 2 1 4 5,然后为了使他们公共最长,想到什么?

  最长不下降子序列!为什么?

  刚开始做的是根据他们的数值,但现在将他们转化成了标号(important)

  对于第一串的标号,很简单,就是1~n(自己对应自己的位置)

  然后剩下的就是在第二串里找最长的递增作为它的重复部分了。

  如果裸的最长不下降子序列(DP),复杂度也是O(n^2),贴一下代码,但道理应该大多数OI的书上都有

  50CODE

#include<cstdio>
#include
<map> using namespace std; inline void read(int &x) { x=0; char ch=getchar(); while (ch<'0'||ch>'9') ch=getchar(); while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); } inline int max(int a,int b) { return a>b?a:b; } const int N=100005; map <int,int> ma; int n,x,num[N],f[N],ans,i,j; int main() { read(n); for (i=1;i<=n;++i) read(x),ma[x]=i; for (i=1;i<=n;++i) read(x),num[i]=ma[x]; for (i=1;i<=n;++i) { f[i]=1; for (j=1;j<i;++j) if (num[j]<num[i]) f[i]=max(f[i],f[j]+1),ans=max(ans,f[i]); } printf("%d",ans); return 0; }

 

  然后优化。方法有两种——二分或树状数组。

  个人还是感觉二分的简单些(因为不会打树状数组的版本)

  用top表示最长不下降子序列的长度;表示用f[i]表示i长度的结尾元素的值。

  仔细观察一下,发现他们满足f[1]<=f[2]<=f[3]……

  然后就可以进行二分优化了

  CODE(常数还挺小)

#include<cstdio>
#include<map>
using namespace std;
const int N=100005;
map <int,int> ma;
int n,x,num[N],f[N],i,top; 
inline void read(int &x)
{
    x=0; char ch=getchar(); 
    while (ch<'0'||ch>'9') ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
}
inline int max(int a,int b) { return a>b?a:b; }
inline int find(int x)
{
    int left=1,right=top,res=0;
    while (left<=right)
    {
        int mid=left+right>>1;
        if (f[mid]<x) res=mid,left=mid+1; else right=mid-1;
    }
    return res;
}
int main()
{
    read(n);
    for (i=1;i<=n;++i)
    read(x),ma[x]=i;
    for (i=1;i<=n;++i)
    read(x),num[i]=ma[x];
    for (i=1;i<=n;++i)
    {
        if (!top) { f[++top]=num[i]; continue; } else
        {
            if (num[i]<f[1]) f[1]=num[i];
            int k=find(num[i]);
            top=max(top,k+1);
            f[k+1]=num[i];
        }
    }
    printf("%d",top);
    return 0;
}

 

posted @ 2017-12-01 13:36  空気力学の詩  阅读(216)  评论(0编辑  收藏  举报