DP模型:
d(i) 以第 i 个元素结尾的最长递增子序列的长度。
那么就有 d(i) = max(d(j)) + 1;(j<i&&a[j]<a[i]),答案 max(d(i)); 时间复杂度为 O(n*n);
下面介绍一个用二分优化的O(nlogn)的算法。
用一个数组g[i] 表示 d 值为 i 的数的最小的 a;即 最长递增子序列为 i 时,最小的 a 是多少。
显然 g[i]<=g[2]<=g[3];
计算d[i] : 需要找到 g中大于等于a[i] 的第一个数 j ,d[i] = j;
更新g : g[j] = a[i] ;
使用STL的lower_bound可以直接求出比a[i] 大的第一个数,用的二分查找实现,总时间O(nlogn);

#include <bits/stdc++.h> using namespace std; int a[1005]; int b[1005]; int main() { int n; scanf("%d",&n); for(int i=0;i<n;i++) scanf("%d",&a[i]); int len = 1; b[0] = a[0]; for(int i=1;i<n;i++) { if(a[i]==b[len-1]) continue; if(a[i]>b[len-1]) b[len++] = a[i]; else { int pos = lower_bound(b,b+len,a[i])-b; b[pos] = a[i]; } } printf("%d ",len); return 0; }

#include <cstdio> #include <cstring> #include <algorithm> using namespace std; #define maxn 1005 #define INF 0x3f3f3f3f int a[1005]; int g[1005]; int binary_search(int *s,int digit,int length) { int left = 0,right = length,mid; while(right!=left) { mid = (left+right)/2; if(digit==s[mid]) return mid; else if(digit<s[mid]) right = mid; else left = mid+1; } return left; } int main() { int n; scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); } memset(g,INF,sizeof(INF)); g[0] = -1; int len = 1; int j; for(int i=1;i<=n;i++) { j = binary_search(g,a[i],len); if(j==len) len++; g[j] = a[i]; } printf("%d ",len-1); return 0; }