最长不下降子序列相关问题
时间复杂度\(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 ;
}

浙公网安备 33010602011771号