【模板题】动态规划 NOI 1759:最长上升子序列

点击打开链接

模板题,复杂度O(nlogn),用到的栈的思想。

但是注意,最终栈中的数据是乱序的。。。

如 1 5 6 2 3 4

栈中依次为1 5 6,读2后栈中为1 2 6,此时最长仍为3,读3后为1 2 3,接着为1 2 3 4,最终结果为4(这个是恰巧是最终求得序列,但大多数情况不是的)

lower_bound(s,s+top,a[i]) 返回一个非递减序列[s, s+top)中的第一个大于等于值a[i]的位置

#include<iostream>
#include<algorithm>
using namespace std;
int a[1001],s[1001];
int main()
{
	int n,i;
	cin>>n;
	for (i=0;i<n;i++)
		cin>>a[i];
	int top=0,*j;
	s[top]=a[0];
	for (i=1;i<n;i++)
	{
		if (a[i]>s[top])
			s[++top]=a[i];
		else
		{	//假如比栈顶值小则在栈中用二分法找第一个>=a[i]的值并替换掉
			//这样使序列的扩展性更强。
			j=lower_bound(s,s+top,a[i]);//本题之精华
			*j=a[i];
		}
	}
	cout<<top+1;
	return 0;
}

复杂度为O(n^2)的代码:

#include<iostream>
#include<algorithm>
using namespace std;
int a[1001],dp[1001]={0};
int main()
{
	int n,i,j,ans;
	cin>>n;
	for (i=0;i<n;i++)
		cin>>a[i];
	ans=0;
	for (i=0;i<n;i++)//序列到i为止 
	{
		dp[i]=1;
		for (j=0;j<i;j++)
			if (a[j]<a[i])//在0~i-1为止的序列中找最长的序列(并加上i)
				dp[i]=max(dp[i],dp[j]+1);
		ans=max(ans,dp[i]);
	}
	cout<<ans;
	return 0;
}

猜你喜欢

转载自blog.csdn.net/always_ease/article/details/80487518