最长上升子序列
两道模板题(一样的)
洛谷 B3637 最长上升子序列
AcWing 895. 最长上升子序列
题目描述
这是一个简单的动规板子题。
给出一个由 \(n(n\le 5000)\) 个不超过 \(10^6\) 的正整数组成的序列。请输出这个序列的最长上升子序列的长度。
最长上升子序列是指,从原序列中按顺序取出一些数字排在一起,这些数字是逐渐增大的。
输入格式
第一行,一个整数 \(n\),表示序列长度。
第二行有 \(n\) 个整数,表示这个序列。
输出格式
一个整数表示答案。
样例 #1
样例输入 #1
6
1 2 4 1 3 4
样例输出 #1
4
提示
分别取出 \(1\)、\(2\)、\(3\)、\(4\) 即可。
标准模版代码
#include <iostream>using namespace std;const int N = 5010;//洛谷板子题是5000所以开大点int n;
int f[N], a[N];int main()
{scanf("%d", &n);for (int i = 0; i < n; i++) {scanf("%d", &a[i]);f[i] = 1;//初始子序列只有一个字母时长度为1}for (int i = 0; i < n; i++)for (int j = 0; j < i; j++){if (a[j] < a[i]) //上升f[i] = max(f[i], f[j] + 1);//最长}int res = 0;for (int i = 0; i < n; i++) res = max(res, f[i]);printf("%d", res);return 0;
}
输出具体方案
代码解释1:int maxLen = *max_element(f.begin(), f.end());
// 代码整体功能:
// 这段代码的目的是在一个整数容器 f
中找到最大的元素,并将其存储在 maxLen
变量中。
// 代码解释:
// 首先,我们使用了标准库中的 max_element
函数。
// max_element
函数接受两个迭代器作为参数,这里是 f.begin()
和 f.end()
。
// f.begin()
表示容器 f
的起始迭代器,f.end()
表示容器 f
的结束迭代器。
// 这个函数会遍历 f
容器中的元素,从 f.begin()
开始,直到 f.end()
之前的元素。
// 然后,它会找出这些元素中的最大值。
// 接着,max_element
函数返回一个迭代器,该迭代器指向容器中最大元素的位置。
// 由于 max_element
函数返回的是一个迭代器,而我们想要的是元素的值,
// 所以在函数调用前使用 *
运算符进行解引用操作。
// 这将迭代器指向的元素的值提取出来,并存储在 maxLen
变量中。
代码解释2:int k = find(f.begin(), f.end(), maxLen) - f.begin();
// 代码整体功能:
// 这段代码的目的是在容器 f
中查找元素 maxLen
的位置,并将该位置存储在变量 k
中。
// 代码解释:
// 首先,使用 find
函数来查找元素。find
函数接受三个参数:
// 1. 起始迭代器 f.begin()
,表示从容器 f
的开始位置开始查找。
// 2. 结束迭代器 f.end()
,表示查找范围截止到容器 f
的末尾位置(不包括 f.end()
所指向的元素)。
// 3. 要查找的元素 maxLen
,它是之前代码中找出的容器 f
中的最大元素。
// find
函数会在 f.begin()
到 f.end()
的范围内查找第一个等于 maxLen
的元素。
// 如果找到了,find
函数会返回一个迭代器,该迭代器指向找到的元素。
// 如果没找到,find
函数会返回 f.end()
。
// 然后,通过 find(f.begin(), f.end(), maxLen) - f.begin()
计算元素 maxLen
在容器中的位置:
// 用 find
函数返回的迭代器减去 f.begin()
迭代器,得到的结果是一个整数,表示元素 maxLen
相对于容器 f
起始位置的偏移量。
// 这个偏移量存储在变量 k
中。
代码解释3:cout << path[i] << " \n"[i == path.size() - 1];
" \n"[i == path.size() - 1];
:这是一个比较巧妙的写法。" \n"是一个字符串常量,它包含一个空格和一个换行符。
[i == path.size() - 1]
是一个条件表达式,当i等于path.size() - 1(即遍历到最后一个元素)时,表达式的值为 1,此时取字符串" \n"中的第二个字符(即换行符\n);否则表达式的值为 0,取字符串" \n"中的第一个字符(即空格)。这样做的效果是,除了最后一个元素输出后换行,其他元素输出后都跟一个空格。
输出具体方案代码
#include <algorithm>
#include <iostream>
#include <vector>using namespace std;int main()
{int n = 0;cin >> n;vector<int> a(n, 0); // 原数组vector<int> f(n, 1); // 状态vector<int> g(n, 0); // 具体方案for (int i = 0; i < n; i++) cin >> a[i];for (int i = 0; i < n; i++){for (int j = 0; j < i; j++){if (a[j] < a[i]){if (f[i] < f[j] + 1){f[i] = f[j] + 1;g[i] = j; // 记录i是由j更新的}}}}int maxLen = *max_element(f.begin(), f.end());int k = find(f.begin(), f.end(), maxLen) - f.begin();vector<int> path;for (int i = 0; i < maxLen; i++){path.push_back(a[k]);k = g[k];}reverse(path.begin(), path.end());for (int i = 0; i < path.size(); i++){cout << path[i] << " \n"[i == path.size() - 1];}return 0;
}