解题思路

使用二分来对朴素版动态规划进行优化
当这个数a[i]比当前f最后一个数f[cnt]还要大时,那么这个数就符合条件f[cnt++] = a[i]
否则 就在f数组里面找第一个比a[i]大的数, 把a[i] 替换给这个位置
毕竟1 5 6 和1 4 6 总是1 4 6 可能性更高一些

比如 2 6 4 5 3
第一次 f:  2           2 > 6
第二次 f:  2 6         4 < 6  f[1] = 4
第三次 f:  2 4         5 > 4  
第四次 f:  2 4 5       3 < 5  f[1] = 3
第五次 f:  2 3 5       结束

关于lower_bound和upper_bound函数

使用方法:lower_bound(f, f + n, x); x是需要查找的数
lower_bound返回的是第一个大于等于x的迭代器, 如果想要计算下标,在后面减去数组的首地址就可以(参考下面代码)
因为这个题的f[i]是严格递增的, 也就是说不会有两个数是相同的, 第一个大于等于x的数就是第一个大于x的数
upper_bound返回的是第一个大于x 的迭代器,计算下标也是减去数组首地址


附代码:

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 1e5 + 10;
int f[N], a[N];//最长递增子序列   数据输入
int main()
{
    int n;
    cin >> n;
    for(int i = 1; i <= n; i ++)cin >> a[i];
    int cnt = 0;
    f[cnt++] = a[1];
    for(int i = 2; i <= n; i ++)
    {
        if(a[i] > f[cnt - 1])f[cnt ++] = a[i];
        else
        {
            int t = lower_bound(f, f + cnt, a[i]) - f;
            f[t] = a[i];
        }
    }
    cout << cnt << endl;
    return 0;
}