51nod 1134最长递增子序列

给出长度为N的数组,找出这个数组的最长递增子序列。(递增子序列是指,子序列的元素是递增的)

例如:5 1 6 8 2 4 5 10,最长递增子序列是1 2 4 5 10。
 
Input
第1行:1个数N,N为序列的长度(2 <= N <= 50000)
第2 - N + 1行:每行1个数,对应序列的元素(-10^9 <= S[i] <= 10^9)
Output
输出最长递增子序列的长度。
Input示例
8
5
1
6
8
2
4
5
10
Output示例
5

动态规划题目,可以令dp[i]为,以ai为末尾的最长上升子序列的长度。
则当i > j,dp[i] > dp[j] dp[i] = max(dp[i],dp[j]+1);

 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <string.h>
 4 #include <algorithm>
 5 using namespace std;
 6 const int Inf = 1<<30;
 7 const int MAX = 50010;
 8 int a[MAX], dp[MAX];
 9 int main(){
10     int n;
11     for(int i = 0; i < MAX; i ++)dp[i] = 0;
12     scanf("%d",&n);
13     for(int i = 0; i < n; i ++)scanf("%d",&a[i]);
14     int res = 0;
15     for(int i = 0; i < n; i ++){
16         dp[i] = 1;
17         for(int j = 0; j < i; j ++){
18             if(a[j] < a[i]){
19                 dp[i] = max(dp[i],dp[j]+1);
20             }
21         }
22         res = max(dp[i],res);
23     }
24     printf("%d
",res);
25     return 0;
26 }

不过由于N最大是50000,用上面的方法肯定会超时的,这是可以用到lower_bound这个函数。用二分的方法,时间复杂度是nlog(n)。

 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <string.h>
 4 #include <algorithm>
 5 using namespace std;
 6 const int Inf = 1<<30;
 7 const int MAX = 50010;
 8 int a[MAX], dp[MAX];
 9 int main(){
10     int n;
11     for(int i = 0; i < MAX; i ++)dp[i] = Inf;
12     scanf("%d",&n);
13     for(int i = 0; i < n; i ++)scanf("%d",&a[i]);
14     for(int i = 0; i < n; i ++){
15         *lower_bound(dp,dp+n,a[i]) = a[i];
16     }
17     printf("%d
",lower_bound(dp,dp+n,Inf)-dp);
18     return 0;
19 }
原文地址:https://www.cnblogs.com/xingkongyihao/p/7201069.html