luogu1020:导弹拦截:最长子序列问题+优化

93 篇文章 0 订阅
26 篇文章 0 订阅

超级好的最长子序列DP元问题,而且还考核了需要做到(nlogn)的优化;


题目连接

题目大意:

1 一个长度是10W的数列,分别求最长不上升子序列 最长上升子序列

2 如果能进将时间复杂度优化到(nlogn),附赠100分!


解题思路1:100分(朴素思维:O(n*n)):

1 DP套路1:问什么设什么:

1.1 对于问题1:f[i]表示:以 i 开头的最长不上升子序列的长度值;

1.2 对于问题2:f[i]表示:以 i 结尾的最长上升子序列的长度值;

2 DP套路2:设前面的任务完成了,i的值和谁有关?
2.1 对于任何一个 i 而言,他前面的每个 j 都和他有关,所以这是一个 n方的询问;

3 DP套路3:初始状态,每个序列最长都是1,所以f[i]值初始化为1。


上代码(朴素版本的:100分):

//luogu1020:导弹拦截
//解法1:简单DP:O(n*n)
//求一个最长不上升子序列,再求一个最长上升子序列
 
#include<bits/stdc++.h>
using namespace std;
const int mx=1e5+10;
int n=0,s1=0,s2=0,f[mx],a[mx];

int main()
{
	while(scanf("%d",&a[++n])!=EOF);
	n--;
	
	for(int i=n;i>=1;i--)//以 i 开头的,最长不上升 
	{
		f[i]=1;
		for(int j=i+1;j<=n;j++)
		{
			if(a[j]<=a[i])
			{
				f[i]=max(f[i],f[j]+1);
			}
		}
		s1=max(s1,f[i]);//求出最长的 
	}
	
	for(int i=1;i<=n;i++)//以 i 结尾,的最长上升 
	{
		f[i]=1;
		for(int j=1;j<i;j++)
		{
			if(a[j]<a[i])
			{
				f[i]=max(f[i],f[j]+1);
			}
		}
		s2=max(s2,f[i]);
	}
	
	printf("%d\n%d",s1,s2);
	
	return 0;
}

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值