传递信息 C++题解

文章介绍了如何通过两种方法解决一个关于身高排序的问题,即在给定一组不同身高的人站成一排的情况下,找出每个人左边和右边比他矮的人中最高的那个人的位置。一种方法使用暴力枚举,另一种方法利用单调栈优化时间复杂度。
摘要由CSDN通过智能技术生成

传递信息

内存限制: 256 MiB 时间限制: 1000 ms 标准输入输出 题目类型: 传统 评测方式: 文本比较

题目描述

现在有n个人站成一行,告诉你每个人的身高。

现在每个人都要找到在他左边,比他矮的人中最高的人的位置。

同时也要找到,在他右边比他矮的人中最高的人的位置。

注意由于他们是站成一行的,所以他们不能越过比他们高的人去看后面的人。也就是说,他只能看到他本人和他的左边(或右边)第一个比他高的人之间的那些人。

请输出每个人左边比他矮的人中最高的人的位置,以及每个人的右边比他矮的人中最高的人的位置(没有的话输出0,位置从1开始)

输入格式

第一行输入一个整数T,表示有T组数据。

每一组数据包含两行,第一行输入一个整数n(0 < n <= 50000),表示有n个人。第二行有n个整数,表示所有人的身高。

数据保证每个人的身高都是不同的,而且身高小于2^31。

输出格式

对于每组数据,输出“Case t:” ( t 表示是第几组数据的答案, t从1开始,双引号不算 )。

然后输出n行,第i行包含两个整数,表示第i个人的左边符合条件的人的位置和右边符合条件的人的位置。如果没有输出0,有就输出位置(位置从1开始)

样例

样例输入

复制2
5
5 2 4 3 1
5
2 1 4 3 5

样例输出

复制Case 1:
0 3
0 0
2 4
0 5
0 0
Case 2:
0 2
0 0
1 4
0 0
3 0
#include <bits/stdc++.h>
using namespace std;
const int maxn = 5e4 + 5;
int n, x;
int a[maxn];
int main() {
	scanf("%d", &x);
	for(int i = 1; i <= x; i++) {
		scanf("%d", &n);
		for(int j = 1; j <= n; j++) {
			scanf("%d", &a[j]);
		} 
		printf("Case %d:\n", i);
		for(int j = 1; j <= n; j++) {
			int Max = 0, t = 0;
			for(int k = j - 1; k >= 1; k--) {
				if(a[k] > a[j]) {
					break;
				} else if(a[k] > Max) {
					t = k;
					Max = a[k];
				} 
			} 
			printf("%d ", t);
			Max = 0, t = 0;
			for(int k = j + 1; k <= n; k++) {
				if(a[k] > a[j]) {
					break;
				} else if(a[k] > Max) {
					t = k;
					Max = a[k];
				} 
			} 
			printf("%d\n", t);
		} 
	} 
	return 0;
} 

这篇暴枚测出时间 500ms 以内,1000ms是可以过的,But要是你对自己要求更高,时间更短,就会用单调栈:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 5e4 + 5;
int n, t;
int a[maxn], l[maxn], r[maxn];
stack<int> s;
int main() {
	scanf("%d", &t);
	for(int i = 1; i <= t; i++) {
		for(int j = 1; j < maxn; j++) {
			l[j] = 0;
			r[j] = 0;
		} 
		while(!s.empty()) {
			s.pop();
		} 
		scanf("%d", &n);
		for(int j = 1; j <= n; j++) {
			scanf("%d", &a[j]);
		} 
		printf("Case %d:\n", i);
		for(int j = 1; j <= n; j++) {
			while(!s.empty() && a[j] > a[s.top()]) {
				l[j] = s.top();
				s.pop();
			} 
			s.push(j);
		} 
		while(!s.empty()) {
			s.pop();
		} 
		for(int j = n; j >= 1; j--) {
			while(!s.empty() && a[j] > a[s.top()]) {
				r[j] = s.top();
				s.pop();
			} 
			s.push(j);
		} 
		for(int j = 1; j <= n; j++) {
			printf("%d %d\n", l[j], r[j]);
		} 
	} 
	return 0;
} 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值