免费午餐--最长下降子序列

http://www.rqnoj.cn/Problem_167.html


一、思路

x1,x2...xn

其中的xi,xi+1...xj 为最长下降子序列

那么x1...xj+1的最长下降子序列 和xi,xi+1一样



f[i] 记录 包含a[i]的最长下降子序列的长度,那么

f[i] = max(f[k] +1 )其中k>=1 && k<i && a[i]<f[k]

即1-i-1里面最长的满足a[i]<f[k]的f[k]


这样从1--n 一重循环

1--i-1 二重循环

时间复杂度n2


-----------

还要考虑的细节 是 0 不算进去


这样可以70个得分点,其余三个超时


===================

后来改f[k] 为记录最长下降子序列长度为i时的最大值

如果f[k] >a[i]

f[++k] = a[i]

否则

在f[k]中找到其中小于a[i]最大的f[j]值

f[j] = a[i] k 长度不变,即最大下降子序列的长度不变


利用二分查找 logN

时间复杂度nLogN 


原本是说a[i]为0的不算进去,结果误写成这个了

导致一个错误点

for (i=1; i<=n&&a[i]; i++)


后面改为了

for (i=1; i<=n; i++)

if (!a[i])

{

continue;

}


AC了



#include <iostream.h>

int a[100001];
int f[100001];

int BinarySearch(int l, int r, int key)
{
	if (l <= r)
	{
		int mid = (l + r) / 2;
		if (f[mid] > key)
		{
			return BinarySearch(mid+1, r, key);
		}
		else
		{
			return BinarySearch(l, mid-1, key);
		}
	}
	else
	{
		return l;
	}

}

int main()
{

    int i, j, n;
	int k = 0;
	//int max = -1;

	cin>>n;

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

	f[0] = 999999;
	k = 0;

	for (i=1; i<=n; i++)
	{
		if (!a[i])
		{
			continue;
		}

		if (f[k]>a[i])
		{
			f[++k] = a[i];
		}
		else
		{
			j = BinarySearch(0, k, a[i]);
			f[j] = a[i];
		}
	}
	//cout<<BinarySearch(1, n, 5);
	cout<<k;



   /*
	f[1] = a[1] ? 1 : 0;
	for (i=2; i<=n; i++)
	{
		max = 0;
		for (j=1; j<i; j++)
		{
			if (j<i && a[j]>a[i] && a[i] && max<f[j])
			{
				max=f[j];
			}
		}

		if (a[i])
		{
			f[i] = max + 1;
		}
	}

	max = 0;
	for (i=1; i<=n; i++)
	{
		if (max<f[i])
		{
			max = f[i];
		}
	}
	

	cout<<max;*/
	return 0;
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值