首页 > 其他分享 >最长上升子序列

最长上升子序列

时间:2024-03-24 20:11:23浏览次数:20  
标签:ch int while 序列 上升 最长 dp getchar

一、题目描述

B3637 最长上升子序列

二、问题简析

2.1 法一:\(O(N^2)\)

令 \(dp[i]=\) 以 \(a_i\) 结尾的上升子序列的最大长度
以 \(a_i\) 结尾的上升子序列有两种可能:

  • 1、仅有 \(a_i\) 一个元素
  • 2、在满足 \(j < i\) 且 \(a_j < a_i\) 的以 \(a_j\) 结尾的上升子序列结尾,加上 \(a_i\)

所以,递归方程为:

\[dp[i]=max(1,dp[j]+1)~~~~~,j<i~and~a_j<a_i \]

最终结果是 \(dp[i]\) 的最大值


#include <bits/stdc++.h>

using namespace std;
typedef long long ll;

int quickin(void)
{
	int ret = 0;
	bool flag = false;
	char ch = getchar();
	while (ch < '0' || ch > '9')
	{
		if (ch == '-')    flag = true;
		ch = getchar();
	}
	while (ch >= '0' && ch <= '9' && ch != EOF)
	{
		ret = ret * 10 + ch - '0';
		ch = getchar();
	}
	if (flag)    ret = -ret;
	return ret;
}

const int MAX = 5e3 + 3;
int A[MAX], n, dp[MAX];

int main()
{
	#ifdef LOCAL
	freopen("test.in", "r", stdin);
	#endif
	
	n = quickin();
	for (int i = 0; i < n; i++)
		A[i] = quickin();
	int ans = 0;
	for (int i = 0; i < n; i++)
	{
		dp[i] = 1;
		for (int j = 0; j < i; j++)
		{
			if (A[j] < A[i])
				dp[i] = max(dp[i], dp[j] + 1);
		}
		ans = max(ans, dp[i]);
	}
	cout << ans << endl;
	
	return 0;
}

2.2 法二:\(O(NlogN)\)

令 \(dp[i]=\) 长度为 \(i+1\) 的上升子序列的末尾元素的最小值。(因为对于相同长度的上升子序列,结尾元素越小,就越有优势)
对于每个 \(dp[i]\),遍历 \(a_j\),若 \(i==0\) 或 \(a_j > dp[i - 1]\),不断更新 \(dp[i]=min(dp[i],a_j)\)。最终,使 \(dp[i] <INF\) 的最大的 \(i+1\) 就是所求。如果按这个思路,仍然是 \(O(N^2)\)。

因为 \(dp[i]\) 是升序,所以我们可以选择用二分搜索来优化。遍历 \(a_j\),在 \(dp[i]\) 中查找首个不小于lower_bound) \(a_j\) 的 \(dp[i]\) ,并赋值 \(a_j\)。最终,使 \(dp[i] <INF\) 的最大的 \(i+1\) 就是所求。


#include <bits/stdc++.h>

using namespace std;
typedef long long ll;

int quickin(void)
{
	int ret = 0;
	bool flag = false;
	char ch = getchar();
	while (ch < '0' || ch > '9')
	{
		if (ch == '-')    flag = true;
		ch = getchar();
	}
	while (ch >= '0' && ch <= '9' && ch != EOF)
	{
		ret = ret * 10 + ch - '0';
		ch = getchar();
	}
	if (flag)    ret = -ret;
	return ret;
}

const int MAX = 5e3 + 3;
const int INF = 1e8;
int A[MAX], n, dp[MAX];

int main()
{
	#ifdef LOCAL
	freopen("test.in", "r", stdin);
	#endif
	
	n = quickin();
	for (int i = 0; i < n; i++)
		A[i] = quickin();
	
	fill(dp, dp + n, INF);
	for (int i = 0; i < n; i++)
	{
		*lower_bound(dp, dp + n, A[i]) = A[i];
	}
	cout << lower_bound(dp, dp + n, INF) - dp << endl;
	
	return 0;
}

标签:ch,int,while,序列,上升,最长,dp,getchar
From: https://www.cnblogs.com/hoyd/p/18092950

相关文章

  • Java序列化之Jackson详解
    目录1Jackson1.1Jackson简介1.2为什么选择Jackson1.3Jackson的基本功能1.3.1将Java对象转换为JSON字符串(序列化)1.3.2将JSON字符串转换为Java对象(反序列化)1.4Jackson库主要方法1.5使用Jackson基本步骤1.5.1添加依赖(Maven或Gradle)1.5.2创建Java对象模型1.5.3使用ObjectMa......
  • 【晴问算法】提高篇—动态规划专题—最长公共子序列
    题目描述现有两个字符串s1​​​​与s2​,求s1​​​​与s2​​​​的最长公共子序列的长度(子序列可以不连续)。输入描述第一行为字符串s1​​,仅由小写字母组成,长度不超过100;第一行为字符串s2​​​,仅由小写字母组成,长度不超过100。输出描述输出一个整数,表示最长公共......
  • 【leetcode】【100268. 最长公共后缀查询】【Trie树】
    Howtoslovethisproblem?Ifwereversethestrings,theproblemchangestofindingthelongestcommonprefix.BuildaTrie,eachnodeisaletterandonlysavesthebestword’sindexineachnode,basedonthecriteria.code:classSolution{publ......
  • Shiro反序列化分析
    前言Shiro,一个流行的web框架,养活了一大批web狗,现在来对它分析分析。Shiro的gadget是CB链,其实是CC4改过来的,因为Shiro框架是自带Commoncollections的,除此之外还带了一个包叫做CommonBeanUtils,主要利用类就在这个包里环境搭建https://codeload.github.com/apache/shiro/zip/shiro......
  • 根据字符数生成序列数
    问题:根据A1的字符数,生成动态的序列数,如A1有5个字符则生成1、2、3、4、5序列数。=ROW(INDIRECT("1:"&LEN(A1)))=SEQUENCE(LEN(A1))Row函数的参数只能是引用,如需要让引用的内容动态化,可以使用间接引用,即嵌套Indirect。Sequence可以直接生成1至A1字符数的序列数。 ......
  • 机器学习算法那些事 | 使用Transformer模型进行时间序列预测实战
    本文来源公众号“机器学习算法那些事”,仅用于学术分享,侵权删,干货满满。原文链接:使用Transformer模型进行时间序列预测实战时间序列预测是一个经久不衰的主题,受自然语言处理领域的成功启发,transformer模型也在时间序列预测有了很大的发展。本文可以作为学习使用Transformer模......
  • 最长子字符串的长度(二)【华为OD机试JAVA&Python&C++&JS题解】
    一.题目-最长子字符串的长度(二)给你一个字符串s,字符串s首尾相连成一个环形,请你在环中找出’l’、‘o’、‘x’字符都恰好出现了偶数次最长子字符串的长度。输入描述:输入是一串小写的字母组成的字符串。输出描述:输出是一个整数补充说明:1<=s.length<=5x10^5......
  • 【锂电池SOC估计】【PyTorch】基于Basisformer时间序列锂离子电池SOC预测研究(python代
     ......
  • 蓝桥杯—蓝肽子序列—动态规划
    蓝肽子序列dp[i][j]表示L1,L2前i,j个字段有多少个公共子序列,对于一个Xi和Yj(L1,L2的前i,j个字段形成序列.如果xi=yj(第i,j字段),则dp[i][j]=dp[i-1][j-1]+1(前面的公共字段加一).否则,dp[i][j]=max(dp[i-1][j],dp[i][j-1]),考虑前后情况的最大值。最后输......
  • P9746 「KDOI-06-S」合并序列
    P9746「KDOI-06-S」合并序列经典区间dp+预处理不难设计状态\(f_{l,r}\)表示\([l,r]\)能否变为一个数,转移也简单,枚举三个区间,满足\(f_{i,a}=f_{b,c}=f_{d,r}=1\)且异或和为\(0\)。复杂度为\(O(n^6)\)。设异或和为\(s_{l,r}\)。考虑优化,瓶颈在于转移需要枚举三个区间......