思路:
对于每一个不同长度的上升子序列,我们有些数字是不需要存储的,比如说如果我们当前的数字能够加在一个较大的数字后面,那我们一定能将当前数字加在一个较小的数字后面(这样范围更大,上升子序列的长度能够更长),所以我们不存储较大的元素到上升子序列之中.那么我们只需要将输入的数据加在当前结尾不大于他但最大的上升子序列后面,这样就能使长度最大.长度+1,更新q[n]
y总的题解我有点懵,能够理解到算法的意思,但是代码感觉有点奇怪,以下这段代码我感觉相对清晰一些:
include [HTML_REMOVED]
include [HTML_REMOVED]
using namespace std;
int n;
const int N = 100010;
int a[N];
int q[N];
int main() {
cin >> n;
for (int i = 0; i < n; i++) {
cin >> a[i];
}
int len = 0;
for (int i = 0; i < n; i++) {
int l = 0, r = len; // 初始化二分范围为 [0, len]
while (l < r) {
int mid = (l + r) / 2; // 注意中点取法 (l+r)/2
if (q[mid] < a[i])
l = mid + 1; // 在右半区查找
else
r = mid; // 在左半区查找
}
//循环结束 l == r,表示找到第一个不小于 a[i] 的位置,需要用a[i]替代当前位置,得到更大范围
q[l] = a[i]; // 更新位置 l 的值
if (l == len) len++; // 如果插入位置是 len,说明长度增加,同时len位置上原本没有值,a[i]就是最小值
}
cout << len << endl;
return 0;
}