1802: 【提高】最长上升子序列LIS(2)

内存限制:128 MB 时间限制:1.000 S
评测方式:文本比较 命题人:
提交:5 解决:2

题目描述

给定一个长度为N的数列,求数值严格单调递增的子序列的长度最长是多少。

输入

第一行包含整数N。
第二行包含N个整数,表示完整序列。
1≤N≤100000,−109≤数列中的数≤109

输出

输出一个整数,表示最大长度。

样例输入 复制

6
1 3 2 8 5 6

样例输出 复制

4

提示

#include<bits/stdc++.h>

using namespace std;
//dp:长度为i的LIS的最后一位最小值是多少
int a[100100], dp[100100];
int i, n, l, r, mid;
int main() {
    scanf("%d", & n);
    for (i = 1; i <= n; i++) {
        scanf("%d", & a[i]);
    }
    //边界
    dp[1] = a[1];
    int len = 1; //LIS 的长度
    //从第2个数开始求解
    for (i = 2; i <= n; i++) {
        //如果 a[1]比 dp最后一位大,a[1]直接续上去,增加 LIS 的长度
        if (a[i] > dp[len]) {
            len++;
            dp[len] = a[i];
        } else {
            //二分查找到dp数组中第1个>=a[1]的元素下标,普换(dp数组一定是递增的)
            l = 1;
            r = len;
            while (l <= r) {
                mid = (l + r) / 2;
                if (a[i] <= dp[mid]) r = mid - 1;
                else l = mid + 1;
            }
            //普换
            dp[l] = a[i];
        }
    }
    printf("%d", len);
    return 0;
}