poj 2533 Longest Ordered Subsequence 最长递增子序列
作者:jostree 转载请注明出处 http://www.cnblogs.com/jostree/p/4098562.html
题目链接:poj 2533 Longest Ordered Subsequence 最长递增子序列
使用$len[i]$表示序列中所有长度为$i$的递增子序列中最小的第$i$个数的值为$len[i]$。对于序列的第j个数$arr[j]$,在$len$中二分查找,找到最后一个小于$arr[j]$的数$len[k]$,如果$len[k]$是序列$len$中最后的一个数,那么在其尾部添加一个数$arr[j]$,否则另$len[k+1]=arr[j]$,直到遍历完$arr$。时间复杂度为O(nlogn)。
代码如下:
1 #include <cstdio> 2 #include <cstdlib> 3 #include <iostream> 4 #include <cstring> 5 #include <vector> 6 #define MAXN 1010 7 using namespace std; 8 int arr[MAXN]; 9 int n; 10 int bs(vector<int> &arr,int num) 11 { 12 int b = 0, e = arr.size()-1; 13 int mid; 14 while( b <= e ) 15 { 16 mid = (b+e)/2; 17 if( arr[mid] <= num ) 18 { 19 b = mid+1; 20 } 21 else 22 { 23 e = mid-1; 24 } 25 } 26 return b; 27 } 28 int solve() 29 { 30 if( n == 0 ) 31 { 32 return 0; 33 } 34 vector<int> len; 35 len.push_back(arr[0]); 36 for( int i = 1 ; i < n ; i++ ) 37 { 38 if( len[len.size()-1] < arr[i]) 39 { 40 len.push_back(arr[i]); 41 } 42 else 43 { 44 len[bs(len, arr[i])] = arr[i]; 45 } 46 } 47 return len.size(); 48 } 49 int main(int argc, char *argv[]) 50 { 51 while( scanf("%d", &n) != EOF ) 52 { 53 for( int i = 0 ; i < n ; i++ ) 54 { 55 scanf("%d", &arr[i]); 56 } 57 printf("%d\n", solve()); 58 } 59 }
同样还有一种$O(n^2)$的动态规划算法。使用$dp[i]$表示到第$i$个数最长的递增子序列的长度。每次用j从0到$i-1$遍历数组,如果发现arr[j]<arr[i],则说明其长度可以加1,最终取最大的长度作为dp[i],即:
\begin{equation}
dp[i] = min(dp[j])+1,(j<i,arr[j]<arr[i])
\end{equation}
代码如下:
1 #include <cstdio> 2 #include <cstdlib> 3 #include <iostream> 4 #include <cstring> 5 #define MAXN 1010 6 using namespace std; 7 int dp[MAXN]; 8 int arr[MAXN]; 9 int n; 10 int solve() 11 { 12 if( n == 0 ) 13 { 14 return 0; 15 } 16 memset(dp, 0, sizeof(dp)); 17 dp[0] = 1; 18 int res = 1; 19 for( int i = 1 ; i < n ; i++ ) 20 { 21 int tmp = 0; 22 for( int j = 0 ; j < i ; j++ ) 23 { 24 if( arr[i] > arr[j] ) 25 { 26 tmp = max(tmp, dp[j]); 27 } 28 } 29 dp[i] = tmp+1; 30 res = max(res, dp[i]); 31 } 32 return res; 33 } 34 int main(int argc, char *argv[]) 35 { 36 while(scanf("%d", &n) != EOF) 37 { 38 for( int i = 0 ; i < n ; i++ ) 39 { 40 scanf("%d", &arr[i]); 41 } 42 printf("%d\n",solve()); 43 } 44 }