最长不下降子序列相关问题

时间复杂度\(O\)\((\)\(n^2\)\()\)的做法

若dp[i]为以a[i]为结尾的最长不下降子序列的长度,则可得:

dp[1] = 1 ;
int ans = 0 ;
for(int i = 2 ; i <= n ; i ++ )
{
    dp[i] = 1 ;
    for(int j = 1 ; j < i ; j ++ )
    {
        if(a[j] <= a[i])
        {
            dp[i] = max(dp[i], dp[j] + 1) ;
            ans = max(ans, dp[i]) ;
        }
    }
}

时间复杂度为\(O\)\((\)\(nlogn\)\()\)的做法

dp[1] = a[1] ;
    int len = 1 ;
    for(int i = 2 ; i <= n ; i ++ )
    {
        if(a[i] >= dp[len]) dp[++len] = a[i] ;
        else{
            int j = upper_bound(dp + 1, dp + len + 1, a[i]) - dp ;
            dp[j] = a[i] ;
        }
    }
    cout << len << endl ;

例题

导弹拦截

#include <bits/stdc++.h>
#define long long i64
using namespace std ;
const int MAXN = 100005 ;
const int INF = 0x3f3f3f ;
int a[MAXN], dp[MAXN] ;
int n , t ;
int main()
{
    while(~scanf("%d", &a[++n])) ; 
    n -- ;
    t = 0 ;
    memset(dp, 0,sizeof(dp)) ;
    dp[0] = INF ;
    for(int i = 1 ; i <= n ; i ++ )
    {
        int l = 0 ;
        int r = t + 1 ;
        while(r - l > 1)
        {
            int mid = ( l + r ) >> 1 ;
            if(dp[mid] >= a[i]) l = mid ;
            else r = mid ;
        }
        int x = l + 1 ;
        if(x > t) t = x ;
        dp[x] = a[i] ;
    }
    cout << t << endl ;
    t = 0 ;
    memset(dp, 0, sizeof(dp)) ;
    dp[0] = 0 ;
    for(int i = 1 ; i <= n ; i ++ )
    {
        int l = 0 ;
        int r = t + 1 ;
        while( r - l > 1 )
        {
            int mid = ( l + r ) >> 1 ;
            if(dp[mid] < a[i]) l = mid ;
            else r = mid ;
        }
        int x = l + 1 ;
        if(x > t) t = x ;
        dp[x] = a[i] ;
    }
    cout << t << endl ;
    return 0 ;
}
posted @ 2023-04-25 13:43  Lwen1243  阅读(24)  评论(0)    收藏  举报