1. 程式人生 > >【dp】求最長上升子序列

【dp】求最長上升子序列

輸出 個數 getchar() 輸入 長度 %d pri get 描述

題目描述

給定一個序列,初始為空。現在我們將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的數字

lower_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\n",len);
    return 0;
}

【dp】求最長上升子序列