2020年蓝桥杯模拟赛 - 10(ST表做RMQ)

不了解ST表的看一下这篇文章:http://www.360doc.com/content/19/0406/15/5315_826796736.shtml

题目

【问题描述】
小明要组织一台晚会,总共准备了 n 个节目。然后晚会的时间有限,他只能最终选择其中的 m 个节目。
这 n 个节目是按照小明设想的顺序给定的,顺序不能改变。
小明发现,观众对于晚会的喜欢程度与前几个节目的好看程度有非常大的关系,他希望选出的第一个节目尽可能好看,在此前提下希望第二个节目尽可能好看,依次类推。
小明给每个节目定义了一个好看值,请你帮助小明选择出 m 个节目,满足他的要求。
【输入格式】
输入的第一行包含两个整数 n, m ,表示节目的数量和要选择的数量。
第二行包含 n 个整数,依次为每个节目的好看值。
【输出格式】
输出一行包含 m 个整数,为选出的节目的好看值。
【样例输入】
5 3
3 1 2 5 4
【样例输出】
3 5 4
【样例说明】
选择了第1, 4, 5个节目。
【评测用例规模与约定】
对于 30% 的评测用例,1 <= n <= 20;
对于 60% 的评测用例,1 <= n <= 100;
对于所有评测用例,1 <= n <= 100000,0 <= 节目的好看值 <= 100000。

思路:首先注意这题的要求,注意我红色加重的部分,尽可能的意思是,在不影响后续选择的情况下,当前选择应为前序可选择的所有数的最大值。

以样例为例:3 1 2 5 4,从中选出三个,那么在选择第一个的时候,可以在保证后两个有的选的情况下,即5 4被保留的情况下,选择3 1 2中最大值,为3,然后从1 2 5 中选择最大值,为5,最后 2 5 4,为4;

再举例 1 4 5 3 2 ,选出来的应该是 5 3 2.

#include<iostream>
#include<cstring>
#include<stack>
#include<ctime>
#define ll long long

using namespace std;

const int N = 100000 + 10;

int lg[N]={-1};
int maxn[N][20];//每个区间内最大值的坐标 
int data[N];

int _pow(int a)
{
	return 1<<a;
}

int query(int l, int r)
{
	int len =lg[r-l+1];
	int a = maxn[l][len-1];
	int b = maxn[r-_pow(len-1)+1][len-1];
	return data[a] > data[b] ? a : b;
}

int main()
{
	int n,m;
	cin>>n>>m;
	for(int i=1; i<=n; i++)
	{
		scanf("%d",&data[i]);
		lg[i] = lg[i/2] + 1;
		maxn[i][0] = i;
	}
	for(int j=1; _pow(j)<=n; j++)
	{
		for(int i=1; i+_pow(j)<=n; i++)
		{
			int a = maxn[i][j-1];
			int b = maxn[i+_pow(j-1)][j-1];
			maxn[i][j] = data[a] > data[b] ? a : b;
		}
	}
	int pos1 = 1, pos2 = n-m+1, pos_max = 1;
	while(pos1 < pos2 && pos2 <= n)
	{
		pos_max = query(pos1, pos2);
		printf("%d ",data[pos_max]);
		pos1 = pos_max + 1;
		pos2++;
	}
	while(pos2 != n+1)
	{
		printf("%d ",data[pos2++]);
	}
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值