nlogn写法。
维护一个 x 序列,存放着一个不下降子序列。(这个子序列并不是答案)
枚举到下一个数字 a[i] 时,若a[i] >= x序列中末尾的数字,则把它加到 x 序列最后面。
否则,找到 x 序列中,第一个大于 a[i] 的值,用 a[i] 更新它,目的是为了使后来的可能的 x 序列更长。
因为 x 序列是有序的,所以这里查找可以用二分查找。
最后的 x 序列的长度就是答案。
#include <iostream> #include <cstdlib> #include <cstdio> #include <cstring> #include <cmath> using namespace std; #define maxn 100000 + 100 int a[maxn], x[maxn]; int found(int l, int r, int s) { int ans = 0; while(l <= r) { int mid = (l+r)/2; if (s <= x[mid]) { ans = mid; r = mid-1; } else l = mid+1; } return ans; } int main() { int n; while(~scanf("%d", &n)) { for (int i = 1; i <= n; i++) scanf("%d", &a[i]); int ans = 0; for (int i = 1; i <= n; i++) { if (ans == 0 || x[ans] <= a[i]) x[++ans] = a[i]; else { int pos = found(1, ans, a[i]); //二分查找第一个大于a[i]的数的位置 x[pos] = a[i]; } } printf("%d ", ans); //最后的 x 序列的长度就是答案 } }