蓝桥杯校内模拟赛 第10题

一、内容

问题描述

小明要组织一台晚会,总共准备了 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。

二、思路

  • 静态查询区间最大值。 首先第一个节目选择的区间为【1, n - m + 1】.查询这个区间的最大值便是第一个节目。得到新的开始位置id。
  • 第二个节目的区间为【id+1, n - m】继续查询这个区间的最大值。然后更新id即可。
  • 第三个节目[id +1, n - m - 1]… 后面的节目类似。

三、代码

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 100005;
int n, m, p[N];
struct Node {
	int maxv, id;
	Node(){maxv = id = 0;}
} tr[N << 2];
void pushup(int id, int l, int r) {
	if (tr[id << 1].maxv >= tr[id << 1 | 1].maxv) {
		tr[id].id = tr[id << 1].id;
		tr[id].maxv = tr[id << 1].maxv;
	} else {
		tr[id].id = tr[id << 1 | 1].id;
		tr[id].maxv = tr[id << 1 | 1].maxv;		
	}
}
void build(int id, int l, int r) {
	if (l == r) {
		tr[id].id = l; tr[id].maxv = p[l];
		return ;
	}
	int mid = (l + r) >> 1;
	build(id << 1, l, mid);
	build(id << 1 | 1, mid + 1, r);
	pushup(id, l, r); 
}
Node query(int id, int l, int r, int x, int y) {
	if (x <= l && r <= y) return tr[id];
	int mid = (l + r) >> 1;
	Node t1, t2;
	if (x <= mid) t1 = query(id << 1, l, mid, x, y);
	if (y > mid) t2 = query(id << 1 | 1, mid + 1, r, x, y);
	if (t1.maxv >= t2.maxv && t1.id != 0) return t1;
	else return t2;	
} 
int main() {
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= n; i++) scanf("%d", &p[i]);
	build(1, 1, n);
	int t = 0; 
	while (m--) {
		//查询区间[t+1, n - m] 
		Node q = query(1, 1, n, t + 1, n - m);
		if (m != 0) printf("%d ", q.maxv);
		else printf("%d", q.maxv);
		t = q.id;
	}
	return 0;
} 
发布了512 篇原创文章 · 获赞 538 · 访问量 8万+

猜你喜欢

转载自blog.csdn.net/qq_41280600/article/details/104857705