题解:洛谷 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

【核心思想】

  1. 问题分析:给定 \(N\) 匹马的比赛用时 \(T_i\)(互不相同),找出用时最短的前三名马匹编号。这是一个结构体排序 + 索引追踪问题,核心在于排序后保持原始编号的映射关系。

  2. 算法选择

    • 结构体排序:将用时和原始编号绑定为结构体,按用时升序排序,取前三个元素的原始编号
  3. 关键步骤

    • 读入数据\(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\)
  4. 时间/空间复杂度

    • 时间复杂度:\(O(N \log N)\),排序主导
    • 空间复杂度:\(O(N)\),结构体数组
  5. 结构体排序与索引追踪的核心思想

    • 数据绑定:将"排序关键字"(用时 \(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
posted @ 2026-08-27 11:05  团爸讲算法  阅读(5)  评论(0)    收藏  举报