【洛谷 B3637】最长上升子序列 题解(动态规划+耐心排序+lower_bound+最长上升子序列)

最长上升子序列

题目描述

这是一个简单的动规板子题。

给出一个由 n ( n ≤ 5000 ) n(n\le 5000) n(n≤5000) 个不超过 1 0 6 10^6 106 的正整数组成的序列。请输出这个序列的最长上升子序列的长度。

最长上升子序列是指,从原序列中按顺序 取出一些数字排在一起,这些数字是逐渐增大的。

输入格式

第一行,一个整数 n n n,表示序列长度。

第二行有 n n n 个整数,表示这个序列。

输出格式

一个整数表示答案。

样例 #1

样例输入 #1

复制代码
6
1 2 4 1 3 4

样例输出 #1

复制代码
4

提示

分别取出 1 1 1、 2 2 2、 3 3 3、 4 4 4 即可。


思路

首先,定义一个整数 n 来存储序列的长度,和一个整数数组 a 来存储序列的元素。同时,定义一个长整型数组 dp 来存储动态规划的状态,dp[i] 存储的是长度为 i 的上升子序列的最小末尾元素。

main 函数中,首先读取序列的长度 n,然后读取序列的元素。然后,对序列的每个元素进行处理,找到在 dp 数组中第一个大于或等于当前元素的位置 pos。这里使用了 lower_bound 函数,这是一个标准库中的二分查找函数。如果 pos 大于当前的最长上升子序列的长度 len,则更新 len。最后,将当前元素放在 dp 数组的 pos 位置。

dp[i] 存储的是长度为 i 的上升子序列的最小末尾元素。当遍历到一个新的元素时,如果这个元素大于所有已有的上升子序列的末尾元素,则可以将这个元素接在最长的上升子序列后面,形成一个更长的上升子序列。否则,找到一个已有的上升子序列,它的末尾元素大于或等于这个元素,然后用这个元素替换那个末尾元素。这样做的目的是尽可能地使上升子序列的末尾元素小,以便有更多的机会接上新的元素。

最后,输出最长上升子序列的长度 len


AC代码

cpp 复制代码
#include <iostream>
#define AUTHOR "HEX9CF"
using namespace std;
using ll = long long;

const int N = 1e6 + 7;

int n;
int a[N];
ll dp[N];

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);

	cin >> n;
	for (int i = 1; i <= n; i++) {
		cin >> a[i];
	}

	int len = 0;
	for (int i = 1; i <= n; i++) {
		int pos = lower_bound(dp + 1, dp + len + 1, a[i]) - dp;
		len = max(len, pos);
		dp[pos] = a[i];
	}
	cout << len << "\n";
	return 0;
}
相关推荐
hetao17338371 小时前
2026-04-09~12 hetao1733837 的刷题记录
c++·算法
6Hzlia1 小时前
【Hot 100 刷题计划】 LeetCode 136. 只出现一次的数字 | C++ 哈希表&异或基础解法
c++·算法·leetcode
MWWZ2 小时前
最近的一些软件更新
opencv·算法·计算机视觉
CoovallyAIHub2 小时前
视频理解新范式:Agent不再被动看视频,LensWalk让它自己决定看哪里
算法·架构·github
CoovallyAIHub2 小时前
斯坦福丨AirVLA:将地面机械臂模型迁移至无人机实现空中抓取,成功率从23%提升至50%
算法·架构·github
无限进步_3 小时前
【C++】只出现一次的数字 II:位运算的三种解法深度解析
数据结构·c++·ide·windows·git·算法·leetcode
Takoony3 小时前
GPU 推理并发的本质:从第一性原理到工程实践
算法·gru
哎嗨人生公众号4 小时前
手写求导公式,让轨迹优化性能飞升,150ms变成9ms
开发语言·c++·算法·机器人·自动驾驶
foundbug9994 小时前
STM32 内部温度传感器测量程序(标准库函数版)
stm32·单片机·嵌入式硬件·算法
Hello.Reader4 小时前
为什么学线性代数(一)
线性代数·算法·机器学习