【每日算法】基础算法——最长上升子序列二(七十四)

题目内容

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

输入格式

第一行包含整数N。
第二行包含N个整数,表示完整序列。

输出格式

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

数据范围

1≤N≤100000 ,
$−10^9$≤数列中的数≤$10^9$

输入样例

7
3 1 2 1 8 5 6

输出样例

4

题解

这里继承上篇最长上升子序列的内容,添加了优化方案。
首先,之前的计算是仍然存在冗余的,具体举个例子来分析一下:如果3能放在8的前面,那么就可以知道,1一定可以放到8的前面。
因此,这里针对第i个元素的最长上升子序列,就可以有如下思考:计算出i之前,长度依次为1~i-1的每个上升子序列结尾能够存放的最小值。这样做的好处就是,当求第a[i]的最长上升子序列时,只需要找出比a[i]小的最大的上升子序列的结尾的数对应的子序列的长度+1就是题目所求。

代码

#include <iostream>
#include <algorithm>

using namespace std;

const int N = 100010;

int n;
int a[N]; //存储每个数
int q[N]; //存储不同长度下上升子序列的结尾最小值,应该严格单调递增

int main()
{
scanf("%d", &n);
for (int i = 0; i < n; i ++ )
scanf("%d", &a[i]);

int len = 0;//存储当前的最大长度
for (int i = 0; i < n; i ++ )
{
int l = 0, r = len;
while (l < r)
{
int mid = l + r + 1 >> 1;
if (q[mid] < a[i]) l = mid;
else r = mid - 1;
}
len = max(len, r + 1);
q[r + 1] = a[i];
}

printf("%d\n", len);

return 0;
}
Author: Frederic Niu
Link: https://www.fredericniu.cn/2021/02/24/【每日算法】基础算法——最长上升子序列二(七十四)/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.
我的公众号