题解:P11185 奖牌排序

思路

每个小朋友可以选择按照金牌数从大到小排序,也可以选择按照银牌数从大到小排序,也可以选择按照铜牌数从大到小排序。

于是不难想到这是一个简单的贪心问题,每个小朋友可以选择他自己认为最优的排序方法

我们假设一个小朋友金牌、银牌、铜牌的排名是 5,1,45,1,45,1,4,那么他的最优排名就是 111

在小朋友自制的排行榜里,如果自己和别的小朋友并列,那么他可以把自己写在最前面。

通过这一点我们不难想到可以通过二分查找找到第一个奖牌数量等于这位小朋友奖牌数的位置,就是这位小朋友的排名。

然后模拟一下样例:

小朋友金牌排名银牌排名铜牌排名最好排名
11141
22111
32322
44333

相信你已经会做了,不会也没关系,我们来看下程序步骤。

程序步骤如下:

  1. 输入数据;
  2. 排序(注意:建议从大到小,当然你也可以从小到大);
  3. 排序后,从前往后计算所有小朋友的排名(取最优排名);
  4. 输出结果。

注意点:

  • 我们如果在 sort() 中使用了 greater <int> () 的话,在 lower_bound() 中也必须使用 greater <int> ()
  • 不需要记录小朋友的编号,直接分开存即可。

代码

#include <bits/stdc++.h>
#define int long long
using namespace std;
int n, a[200010], b[200010], c[200010];
struct node {
	int au, ag, cu; // 结构体存每个小朋友的金、银、铜牌数量
} input[200010];
signed main() {
	ios :: sync_with_stdio(false);
	cin . tie(nullptr);
	cin >> n;
	for (int i = 1; i <= n; i ++) {
		cin >> input[i] . au >> input[i] . ag >> input[i] . cu; // 输入
		a[i] = input[i] . au; // a数组用来保存小朋友们的金牌数量
		b[i] = input[i] . ag; // b数组用来保存小朋友们的银牌数量
		c[i] = input[i] . cu; // c数组用来保存小朋友们的铜牌数量
	}
	sort(a + 1, a + n + 1, greater <int> ()), sort(b + 1, b + n + 1, greater <int> ()), sort(c + 1, c + n + 1, greater <int> ()); // 将每种奖牌数量单独排序,因为他们互不干扰
	for (int i = 1; i <= n; i ++) {
		int minn = INT_MAX;
		minn = min(minn, (int)(lower_bound(a + 1, a + n + 1, input[i] . au, greater <int> ()) - a));
		minn = min(minn, (int)(lower_bound(b + 1, b + n + 1, input[i] . ag, greater <int> ()) - b));
		minn = min(minn, (int)(lower_bound(c + 1, c + n + 1, input[i] . cu, greater <int> ()) - c));
    // 取小朋友最优的排名(使用 lower_bound)
		cout << minn << endl;
	}
	return 0;
}

最后希望大家可以关注与点赞,感谢支持。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值