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\n",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\n",lower_bound(dp,dp+n,Inf)-dp); 18 return 0; 19 }