读入时按名字结尾字母分 26 个桶,桶内按(评分降序、同分先读入在前)排好序,询问直接取桶内第 k 个名字。
OJ: roj
题目 ID: 10008
难度:普及-
标签:排序分桶模拟
创建: 2026-10-02 17:36
更新: 2026-10-07 12:15
题目描述
牛半仙有 Orz YYR tql。输入第一行
样例:输入 5 2 / aaa 1 / aa 2 / a 3 / ab 3 / bb 4 / b 2 / a 4,输出 ab / Orz YYR tql。
思路
名字结尾字母只有 26 种,读入时按结尾字母分 26 个桶,每个桶内按「评分降序、同分先读入在前」排好序,排序后桶内第 Orz YYR tql,否则按下标直接取名字,单次询问
参考代码
Python 版:
python
#!/usr/bin/env python3
# Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
# rbook: -> https://rbook.roj.ac.cn https://rbook2.roj.ac.cn
# rainboy的学习导航网站: https://idx.roj.ac.cn
# create_at: 2026-10-02 17:40
# update_at: 2026-10-04 09:12
import sys
from collections import defaultdict
ORZ = b"Orz YYR tql" # 该结尾字母下凑不够第 k 名时的回答
def solve() -> None:
data = iter(sys.stdin.buffer.read().split()) # token 流:名字与数字都按 next() 顺序消费
n, m = int(next(data)), int(next(data))
# 按名字结尾字母分桶:排序键 (-评分, 读入序号),评分大在前、同分先读入在前
buckets: dict[str, list[tuple[int, int, bytes]]] = defaultdict(list)
for i in range(2, 2 + 2 * n, 2):
name = next(data)
buckets[name[-1:]].append((-int(next(data)), i, name))
for ranked in buckets.values():
ranked.sort()
out: list[bytes] = []
for j in range(2 * n, 2 * n + 2 * m, 2):
ranked = buckets.get(next(data)) # 询问的结尾字母
k = int(next(data))
out.append(ranked[k - 1][2] if ranked is not None and len(ranked) >= k else ORZ)
sys.stdout.buffer.write(b"\n".join(out) + b"\n")
if __name__ == "__main__":
solve()C++ 版(同一算法):
cpp
/**
* Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
* rbook: -> https://rbook.roj.ac.cn https://rbook2.roj.ac.cn
* rainboy的学习导航网站: https://idx.roj.ac.cn
* create_at: 2026-10-04 21:38
* update_at: 2026-10-04 21:38
*/
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
using namespace std;
typedef long long ll;
struct Girl {
ll score; // 评分
ll id; // 读入编号,从 1 开始
string name;
};
vector<Girl> bucket[26]; // bucket[c] 存放名字以字符 'a' + c 结尾的妹子
ll cnt[26]; // cnt[c] = bucket[c] 中的元素个数
// 排序比较:评分大的在前,评分相同时先读入(编号小)的在前
bool cmp_girl(const Girl &a, const Girl &b) {
if (a.score != b.score) return a.score > b.score;
return a.id < b.id;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
ll n, m;
cin >> n >> m;
// 读入时按名字的最后一个字母分桶,顺便记下读入编号
for (ll i = 1; i <= n; i++) {
string name;
ll score;
cin >> name >> score;
int c = name[name.size() - 1] - 'a';
Girl g;
g.score = score;
g.id = i;
g.name = name;
bucket[c].push_back(g);
cnt[c]++;
}
// 每个桶内部排好序,桶内下标 k - 1 就是该字母下第 k 大的名字
for (int c = 0; c < 26; c++) {
sort(bucket[c].begin(), bucket[c].end(), cmp_girl);
}
for (ll q = 1; q <= m; q++) {
char x;
ll k;
cin >> x >> k;
int c = x - 'a';
if (k > cnt[c]) {
cout << "Orz YYR tql" << endl;
} else {
cout << bucket[c][k - 1].name << endl;
}
}
return 0;
}