QDUOJ计科寒假测试赛01-LB竟然当众开车!-贪心求最长下降子序列

题目描述:

LB有n列火车。

火车按照序号从1~n排列在入口轨道上(1号火车在最前方,即下图入口最右方),火车的行进方向都是从左至右。

有钱的LB想在入口与出口之间修建k条中部轨道,火车可从入口轨道进入任意一条中部轨道,最后都从出口轨道驶出。

LB想让火车按照价格递增的顺序驶出,便找到JZL,问至少要修建多少条中部轨道,可是JZL天生愚钝,你能帮他解决这个问题吗?

注:下图中的数字是价格而不是序号。
在这里插入图片描述

输入描述:

第一行输入一个整数n,表示火车的数量。

接下来n行,每行一个整数,第i+1行表示第i列火车的价格ai。

0<n<=1e5

0<ai<=1e5,且ai互不相等

输出描述:

输出一个整数k。

输入样例:

9
8
4
2
5
3
9
1
6
7

输出样例:

4

核心思想:

  1. 进入相同中部轨道的火车,前后顺序不会改变;
  2. 进入不同中部轨道的火车,前后顺序可能改变。

由1可知:任意一条中部轨道上的火车,进入中部轨道的顺序应当是上升子序列,如下图,(第一条中部轨道8在前,9在后)

在这里插入图片描述输入数组为8 4 2 5 3 9 1 6 7 (8在前,9在后)
四条中部轨道对应如下四条上升子序列
8 9
4 5 6 7
2 3
1

此题转换为求输入数组至少可以分为多少个上升子序列
即求输入数组的最长下降子序列的长度

采用贪心的方式求最长下降子序列的图解:

在这里插入图片描述
上图每一列是一个上升子序列,
最下面一行8 4 2 1就是一个最长下降子序列
上图的列数就是最长下降子序列的长度cnt,也是代码中数组b的长度。

代码如下:

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=1e5+50;
int a[N],b[N];
bool cmp(int x,int y){ return x>y;}
int main()
{
	int n,cnt=0;
	cin>>n;
	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
	for(int i=1;i<=n;i++){
		//贪心找到数组b中第一个小于a[i]的位置 
		int pos=lower_bound(b,b+cnt,a[i],cmp)-b;
		b[pos]=a[i];
		//若数组b中没有比a[i]小的数,那么lower_bound会返回cnt 
		if(pos==cnt) cnt++;
	}
	cout<<cnt<<endl;
	return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值