B3637 最长上升子序列

最长上升子序列

题目描述

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

给出一个由 n ( n ≤ 5000 ) n(n\le 5000) n(n5000) 个不超过 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 即可。

分析

状态:设f[i]是以i为结束的最长上升子序列的长度
答案: a n s = max ⁡ i = 1 n { f [ i ] } ans=\max_{i=1}^n\{f[i]\} ans=maxi=1n{f[i]}
这里我们考虑已经求出两个状态:i,j,我们用A数组表示原序列,f数组记录状态,我们加个条件:
A [ i ] < A [ j ]  且  f [ i ] = f [ j ] A[i]A[i]<A[j]  f[i]=f[j]
则对于以后的状态,我们更希望从i上转移,所以我们可以保留相同的f值的最小A,即设g[i],表示f[j]=i时最小的a[j],那么g数组必定不降,可以二分查找

代码

#include
using namespace std;
const int M=20,N=1e6;
int f[N],g[N],a[N],n;
int main(){
	cin>>n;
	memset(g,0x3f,sizeof g);
	for (int i=0;i<n;i++) cin>>a[i];
	int maxn=0;
	for (int i=0;i<n;i++){
		int k=lower_bound(g+1,g+1+n,a[i])-g;
		f[i]=k;
		maxn=max(f[i],maxn);
		g[k]=a[i];
	}
	cout<<maxn;
	return 0;
}

时间复杂度O(nlogn)

你可能感兴趣的:(算法,c++,数据结构)