• 洛谷【P1439】【模板】最长公共上升子序列


    浅谈(DP)https://www.cnblogs.com/AKMer/p/10437525.html

    题目传送门:https://www.luogu.org/problemnew/show/P1439

    (f[i][j])表示在(a)序列中([1,i])(b)序列的([1,j])的最长公共子序列。

    那么(f[i][j]=max){(f[i-1][j],f[i][j-1],f[i-1][j-1]+(a[i]==b[j]))}

    初始都为(0)(f[n][n])即为答案。

    时间复杂度:(O(n^2))

    空间复杂度:(O(n^2))

    代码如下:

    #include <cstdio>
    #include <algorithm>
    using namespace std;
    
    const int maxn=1e3+5;
    
    int n;
    int f[maxn][maxn];
    int a[maxn],b[maxn];
    
    int read() {
        int x=0,f=1;char ch=getchar();
        for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
        for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
        return x*f;
    }
    
    int main() {
        n=read();
        for(int i=1;i<=n;i++)
            a[i]=read();
        for(int i=1;i<=n;i++)
            b[i]=read();
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++) {
                f[i][j]=max(f[i][j],f[i-1][j-1]+(a[i]==b[j]));
                f[i][j]=max(f[i][j],max(f[i][j-1],f[i-1][j]));
            }
        printf("%d
    ",f[n][n]);
        return 0;
    }
    

    由于问题给出的是一个排列,所以我们可以把第二个序列变成相应的在第一个序列中的位置,那么这个时候最长公共子序列就变成了第二个序列的最长上升子序列了,这一个子序列会保证都在两个序列里出现过。

    时间复杂度:(O(nlogn))

    空间复杂度:(O(n))

    代码如下:

    #include <cstdio>
    #include <algorithm>
    using namespace std;
    #define low(i) ((i)&(-(i)))
    
    const int maxn=1e5+5;
    
    int n;
    int pos[maxn];
    
    int read() {
        int x=0,f=1;char ch=getchar();
        for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
        for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
        return x*f;
    }
    
    struct tree_array {
        int c[maxn];
    
        void add(int pos,int v) {
            for(int i=pos;i<=n;i+=low(i))
                c[i]=max(c[i],v);
        }
    
        int query(int pos) {
            int res=0;
            for(int i=pos;i;i-=low(i))
                res=max(res,c[i]);
            return res;
        }
    }T;
    
    int main() {
        n=read();
        for(int i=1;i<=n;i++) {
            int x=read();
            pos[x]=i;
        }
        for(int i=1;i<=n;i++) {
            int x=read();x=pos[x];
            int f=T.query(x-1)+1;
            T.add(x,f);
        }
        printf("%d
    ",T.query(n));
        return 0;
    }
    
  • 相关阅读:
    HDU 1249 三角形
    HDU 1799 循环多少次?
    UVA 12219-Common Subexpression Elimination
    POJ 2253-Frogger(最小生成树的最大权)
    OpenCV之参数不匹配问题
    vs2017-关于配置属性管理器的问题
    D
    圆桌会议
    F
    B
  • 原文地址:https://www.cnblogs.com/AKMer/p/10437542.html
Copyright © 2020-2023  润新知