解题思路
使用二分来对朴素版动态规划进行优化
当这个数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;
}