题解:P11185 奖牌排序
思路
每个小朋友可以选择按照金牌数从大到小排序,也可以选择按照银牌数从大到小排序,也可以选择按照铜牌数从大到小排序。
于是不难想到这是一个简单的贪心问题,每个小朋友可以选择他自己认为最优的排序方法。
我们假设一个小朋友金牌、银牌、铜牌的排名是 5 , 1 , 4 5,1,4 5,1,4,那么他的最优排名就是 1 1 1。
在小朋友自制的排行榜里,如果自己和别的小朋友并列,那么他可以把自己写在最前面。
通过这一点我们不难想到可以通过二分查找找到第一个奖牌数量等于这位小朋友奖牌数的位置,就是这位小朋友的排名。
然后模拟一下样例:
小朋友 | 金牌排名 | 银牌排名 | 铜牌排名 | 最好排名 |
---|---|---|---|---|
1 | 1 | 1 | 4 | 1 |
2 | 2 | 1 | 1 | 1 |
3 | 2 | 3 | 2 | 2 |
4 | 4 | 3 | 3 | 3 |
相信你已经会做了,不会也没关系,我们来看下程序步骤。
程序步骤如下:
- 输入数据;
- 排序(注意:建议从大到小,当然你也可以从小到大);
- 排序后,从前往后计算所有小朋友的排名(取最优排名);
- 输出结果。
注意点:
- 我们如果在
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;
}
最后希望大家可以关注与点赞,感谢支持。