• 【dp】求最长上升子序列


    题目描述

    给定一个序列,初始为空。现在我们将1到N的数字插入到序列中,每次将一个数字插入到一个特定的位置。我们想知道此时最长上升子序列长度是多少?

    输入

    第一行一个整数N,表示我们要将1到N插入序列中,接下是N个数字,第k个数字Xk,表示我们将k插入到位置Xk(0<=Xk<=k-1,1<=k<=N)

    输出

    1行,表示最长上升子序列的长度是多少。

    样例输入

    3

    0 0 2

    样例输出

    2

    提示

    100%的数据 n<=100000

     

    【思路】:
    就是用dp表示前i个的最长上升子序列长度,注意一开始赋值成1(坑了我一把,呜呜呜),然后考虑当前点放到序列里不,然后就ok了.

     

    代码:O(N2)

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    #include<stack>
    #include<vector>
    #include<map>
    #include<string>
    #include<cstring>
    using namespace std;
    inline int read() {
        char c = getchar();
        int x = 0, f = 1;
        while(c < '0' || c > '9') {
            if(c == '-') f = -1;
            c = getchar();
        }
        while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
        return x * f;
    }
    int a[10080],n,ans,dp[10000];
    
    int main() {
        cin>>n;
        for(int i=1; i<=n; ++i) {
            cin>>a[i];
            dp[i]=1;
        }
        for(int i=2; i<=n; ++i) {
            for(int j=1; j<i; ++j) {
                if(a[i]>a[j]&&dp[j]+1>dp[i]) {
                    dp[i]=dp[j]+1;
                }
            }
        }
        for(int i=1; i<=n; ++i) {
            if(dp[i]>ans) {
                ans=dp[i];
            }
        }
        cout<<ans;
        return 0;
    }

    优化代码:O(n*logn)

    【思路】:
    用二分查找,可是二分很难怎么办?

    lower_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于或等于num的数字
    
    upper_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于num的数字

    竟然可以直接二分,那还怂个P。

    更多解释见https://www.cnblogs.com/wxjor/p/5524447.html(和这篇博客学的)

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    #include<stack>
    #include<vector>
    #include<map>
    #include<string>
    #include<cstring>
    using namespace std;
    const int maxn=99999;
    inline int read() {
        char c = getchar();
        int x = 0, f = 1;
        while(c < '0' || c > '9') {
            if(c == '-') f = -1;
            c = getchar();
        }
        while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
        return x * f;
    }
    int a[maxn],d[maxn],n;
    int len=1;
    int main() {
        scanf("%d",&n);
        for(int i=1; i<=n; i++)
            scanf("%d",&a[i]);
        d[1]=a[1];
        for(int i=2; i<=n; i++) {
            if(a[i]>d[len])
                d[++len]=a[i];
            else {
                int j=lower_bound(d+1,d+len+1,a[i])-d;
                d[j]=a[i];
            }
        }
        printf("%d
    ",len);
        return 0;
    }
  • 相关阅读:
    文本属性和字体属性
    BZOJ 2724: [Violet 6]蒲公英
    BZOJ4010: [HNOI2015]菜肴制作
    BZOJ 2160: 拉拉队排练
    HDU-5157Harry and magic string
    HDU-5421Victor and String
    BZOJ2565: 最长双回文串(回文树)
    BZOJ3676: [Apio2014]回文串(回文树)
    BZOJ 3195: [Jxoi2012]奇怪的道路(状压dp)
    BZOJ1758: [Wc2010]重建计划(01分数规划+点分治+单调队列)
  • 原文地址:https://www.cnblogs.com/pyyyyyy/p/10770939.html
Copyright © 2020-2023  润新知