题解:洛谷 AT_abc440_b Trifecta
【题目来源】
洛谷:AT_abc440_b [ABC440B] Trifecta - 洛谷
【题目描述】
编号为 \(1\) 至 \(N\) 的 \(N\) 匹马参加了一场比赛。
所有马匹同时出发,马匹 \(i\) 从起点到终点用时 \(T_i\) 秒。
找出获得第 \(1\) 名、第 \(2\) 名和第 \(3\) 名的马匹编号。保证所有 \(T_i\) 互不相同。
【输入】
输入以标准输入的形式给出,格式如下:
\(N\)
\(T_1\) \(\dots\) \(T_N\)
【输出】
输出第 \(1\) 名、第 \(2\) 名和第 \(3\) 名的马匹编号,按此顺序,用空格分隔。
【输入样例】
4
100 110 105 95
【输出样例】
4 1 3
【核心思想】
-
问题分析:给定 \(N\) 匹马的比赛用时 \(T_i\)(互不相同),找出用时最短的前三名马匹编号。这是一个结构体排序 + 索引追踪问题,核心在于排序后保持原始编号的映射关系。
-
算法选择:
- 结构体排序:将用时和原始编号绑定为结构体,按用时升序排序,取前三个元素的原始编号
-
关键步骤:
- 读入数据:\(N\) 和 \(T[1..N]\)
- 构建结构体数组:\(a[i].t = T_i\),\(a[i].idx = i\)
- 按用时升序排序:
sort(a+1, a+n+1, cmp),比较函数按 \(t\) 升序 - 输出结果:\(a[1].idx\)、\(a[2].idx\)、\(a[3].idx\)
-
时间/空间复杂度:
- 时间复杂度:\(O(N \log N)\),排序主导
- 空间复杂度:\(O(N)\),结构体数组
-
结构体排序与索引追踪的核心思想:
- 数据绑定:将"排序关键字"(用时 \(t\))和"附属信息"(原始编号 \(idx\))封装为结构体,确保排序后仍能追溯原始身份
- 稳定排序的不必要性:题目保证所有 \(T_i\) 互不相同,无需处理相等的情况,简单升序即可
- 前 \(K\) 大/小问题的通用解法:排序后取前 \(K\) 个元素是求前 \(K\) 名最直观的方法,虽然可用堆优化到 \(O(N \log K)\),但对于 \(N \leq 35\) 的数据范围,排序已足够高效
- 适用于基础排序、索引映射、前 \(K\) 名查询类入门问题
【算法标签】
入门 #其他排序
【代码详解】
#include <bits/stdc++.h>
using namespace std;
const int N = 35;
int n;
struct Node
{
int t, idx; // t: 时间, idx: 原始编号
} a[N];
// 比较函数:按时间t升序排序
bool cmp(Node x, Node y)
{
return x.t < y.t;
}
int main()
{
cin >> n;
for (int i = 1; i <= n; i++)
{
cin >> a[i].t; // 输入时间
a[i].idx = i; // 记录原始编号
}
// 按时间升序排序
sort(a + 1, a + n + 1, cmp);
// 输出前3个最短时间的原始编号
for (int i = 1; i <= 3; i++)
cout << a[i].idx << " ";
cout << endl;
return 0;
}
【运行结果】
4
100 110 105 95
4 1 3
浙公网安备 33010602011771号