403 字
2 分钟

最长上升子序列题解

2025-04-16
浏览量 加载中...

1. base#

这是一个线性dp的版本,它的数据范围在1000

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

输入格式

第一行包含整数 NN

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

输出格式

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

数据范围

1N10001≤N≤1000109数列中的数109−10^9≤数列中的数≤10^9

输入样例

7
3 1 2 1 8 5 6

输出样例

4

DP分析#

23558fd23229a69e3a50d02b8e8ac61

代码#

#include <bits/stdc++.h>
using namespace std;
const int N = 1010;
int n;
int w[N], f[N];
int main()
{
cin >> n;
for (int i = 1; i <= n; i ++ ) cin >> w[i];
for (int i = 1; i <= n; i ++ )
{
f[i] = 1;
for (int j = 1; j < i; j ++ )
if (w[i] > w[j])
f[i] = max(f[j] + 1, f[i]);
}
int res = -1;
for (int i = 1;i <= n; i ++ )
res = max(res, f[i]);
cout << res << endl;
return 0;
}

2. 进阶#

数据范围更大,使用DP会TLE(Time Limit Error)

数据范围

1N10000001≤N≤1000000109数列中的数109−10^9≤数列中的数≤10^9

分析#

存储每个长度中最后的数最小的情况,必定这个数组是单调递增的,可以用二分。

代码#

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int a[N], q[N];
int n;
int main()
{
cin >> n;
for (int i = 0; i < n; i ++ ) cin >> a[i];
int len = 0;
q[0] = -2e9;
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];
}
cout << len << endl;
return 0;
}

文章分享

如果这篇文章对你有帮助,欢迎分享给更多人!

最长上升子序列题解
https://printsdf.dpdns.org/posts/最长上升子序列题解/
作者
printsdf
发布于
2025-04-16
许可协议
CC BY-NC-SA 4.0
最后更新于 2025-04-16,距今已过 373 天

部分内容可能已过时

评论区

Profile Image of the Author
printsdf
Hello, I'm printsdf.
公告
欢迎来到我的博客!这是一则示例公告。
音乐
封面

音乐

暂未播放

0:00 0:00
暂无歌词
分类
标签
站点统计
文章
37
分类
12
标签
14
总字数
47,088
运行时长
0
最后活动
0 天前

目录