#P2985. 比赛的冠亚季军(100分)
          
                        
                                    
                      
        
              - 
          
          
                      1000ms
            
          
                      Tried: 628
            Accepted: 101
            Difficulty: 6
            
          
          
          
                       所属公司 : 
                              华为od
                                
            
                      
          
 
- 
                        算法标签>模拟          
 
比赛的冠亚季军(100分)
题目描述
有 N 个运动员,他们的 id 为  0 到  N-1 。每位运动员的实力值用一个正整数表示。所有运动员按照如下规则进行比赛,最终决出冠亚季军:
- 每轮比赛中,相邻的运动员进行比赛,胜者进入下一轮。实力值大的运动员获胜;若实力值相等,
id小的获胜。 - 如果当前轮比赛中有奇数个运动员,则最后一个运动员轮空,直接进入下一轮。
 - 比赛进行到最终的两名运动员时,获胜者为冠军,失败者为亚军。随后,亚军和上一轮被淘汰的运动员中实力最强的进行比赛,胜者为季军。
 
解题思路
- 使用递归的方式模拟比赛过程,逐轮减少选手数量。
 - 对于每一轮比赛,比较相邻选手,获胜者进入下一轮;若选手数量为奇数,最后一名直接晋级。
 - 比赛进行到最终两人时,记录冠亚军的 
id,并决定季军为上一轮中实力最强的未进入冠亚军的选手。 - 返回冠亚季军的 
id。 
代码实现
Python代码
def cmp(x, y):
    # 比较两名选手,返回实力强者和弱者(以tuple形式)
    if x[0] > y[0]:  # 实力高者胜
        return (x, y)
    elif x[0] < y[0]:  # 实力低者败
        return (y, x)
    else:  # 实力相等,id 小者胜
        if x[1] < y[1]:
            return (x, y)
        else:
            return (y, x)
def solve(players):
    n = len(players)
    if n == 3:  # 特殊情况:只有三名选手
        k1 = cmp(players[0], players[1])  # 比较前两名
        k2 = cmp(k1[0], players[2]) # 冠亚军
        return [k2[0][1], k2[1][1], k1[1][1]]
    elif n == 4:  # 特殊情况:四名选手
        k1 = cmp(players[0], players[1])
        k2 = cmp(players[2], players[3])
        k3 = cmp(k1[0], k2[0])  # 冠亚军
        k4 = cmp(k1[1], k2[1])  # 季军争夺
        return [k3[0][1], k3[1][1], k4[0][1]]
    
    win_players = []
    for i in range(1, n, 2):  # 每两名选手比赛
        win_players.append(cmp(players[i-1],players[i])[0])
    if n % 2 == 1:  # 奇数时最后一人轮空晋级
        win_players.append(players[-1])
    
    return solve(win_players)
# 输入处理
p = [int(i) for i in input().split()]
players = [(p[i], i) for i in range(len(p))]
print(' '.join([str(i) for i in solve(players)]))
Java代码
import java.util.*;
public class Main {
    public static void main(String[] args) {
        // 创建扫描器对象,用于读取输入
        Scanner sc = new Scanner(System.in);
        
        // 读取一行输入并用空格分割
        String[] input = sc.nextLine().split(" ");
        int n = input.length;  // 选手数量
        Long[][] players = new Long[n][2];  // 用 Long 类型表示选手数据(实力值和选手ID)
        
        // 将输入的数据填充到 players 数组中
        for (int i = 0; i < n; i++) {
            players[i][0] = Long.parseLong(input[i]);  // 解析实力值为 Long 类型
            players[i][1] = (long) i;  // 选手的 ID(从 0 开始)
        }
        
        // 调用 solve 方法进行比赛并输出结果
        List<Long> result = solve(players);
        System.out.println(result.get(0) + " " + result.get(1) + " " + result.get(2));
    }
    
    // solve 方法根据选手数据进行比赛,返回冠军、亚军和季军
    public static List<Long> solve(Long[][] players) {
        int n = players.length;  // 获取选手数量
        
        // 特殊情况:当选手数量为 3 时,直接进行比赛
        if (n == 3) {
            Long[][] k1 = cmp(players[0], players[1]);  // 第一轮比赛,比较前两位选手
            Long[][] k2 = cmp(k1[0], players[2]);  // 冠军与第三位选手对决
            return Arrays.asList(k2[0][1], k2[1][1], k1[1][1]);  // 返回冠军、亚军和季军的 ID
        } 
        // 特殊情况:当选手数量为 4 时,进行两轮比赛
        else if (n == 4) {
            Long[][] k1 = cmp(players[0], players[1]);  // 第一轮比赛,前两位选手
            Long[][] k2 = cmp(players[2], players[3]);  // 第二轮比赛,后两位选手
            Long[][] k3 = cmp(k1[0], k2[0]);  // 冠亚军对决
            Long[][] k4 = cmp(k1[1], k2[1]);  // 季军争夺
            return Arrays.asList(k3[0][1], k3[1][1], k4[0][1]);  // 返回冠军、亚军和季军的 ID
        }
        
        // 进行递归比赛,处理选手数大于 4 的情况
        List<Long[]> winPlayers = new ArrayList<>();
        for (int i = 1; i < n; i += 2) {
            winPlayers.add(cmp(players[i - 1], players[i])[0]);  // 每对选手进行比较,记录胜者
        }
        // 如果选手数量是奇数,最后一名选手自动进入下一轮
        if (n % 2 == 1) {
            winPlayers.add(players[n - 1]);
        }
        
        // 递归处理剩下的选手,直到剩下 3 个选手
        return solve(winPlayers.toArray(new Long[0][]));
    }
    
    // 比较两名选手,返回实力强者和弱者
    public static Long[][] cmp(Long[] x, Long[] y) {
        // 如果 x 的实力值大于 y,或者相等时 x 的 ID 小于 y,返回 x 强
        if (x[0] > y[0] || (x[0] == y[0] && x[1] < y[1])) {
            return new Long[][] {x, y};
        } else {
            return new Long[][] {y, x};  // 否则返回 y 强
        }
    }
}
C++代码
#include <iostream>
#include <vector>
#include <algorithm>
#define LL long long
using namespace std;
// 比较两名选手,返回实力强者和弱者
pair<pair<LL, LL>, pair<LL, LL>> cmp(pair<LL, LL> x, pair<LL, LL> y) {
    if (x.first > y.first || (x.first == y.first && x.second < y.second)) {
        return {{x.first, x.second}, {y.first, y.second}};
    } else {
        return {{y.first, y.second}, {x.first, x.second}};
    }
}
vector<LL> solve(vector<pair<LL, LL>>& players) {
    LL n = players.size();
    if (n == 3) {
        auto k1 = cmp(players[0], players[1]);
        auto k2 = cmp(k1.first, players[2]); // 冠亚军
        return {k2.first.second, k2.second.second, k1.second.second};
    } else if (n == 4) {
        auto k1 = cmp(players[0], players[1]);
        auto k2 = cmp(players[2], players[3]);
        auto k3 = cmp(k1.first, k2.first); // 冠亚军
        auto k4 = cmp(k1.second, k2.second); // 季军争夺
        return {k3.first.second, k3.second.second, k4.first.second};
    }
    vector<pair<LL, LL>> winPlayers;
    for (LL i = 1; i < n; i += 2) {
       winPlayers.push_back(cmp(players[i - 1], players[i]).first);
    }
    if (n % 2 == 1) {
        winPlayers.push_back(players[n - 1]);
    }
    return solve(winPlayers);
}
int main() {
    LL n;
    vector<pair<LL, LL>> players;
    LL val;
    while (cin >> val) {
        players.emplace_back(val, players.size());
    }
    vector<LL> result = solve(players);
    for (LL i = 0; i < result.size(); ++i) {
        cout << result[i];
        if (i < result.size() - 1) cout << " ";
    }
    return 0;
}
        题目内容
有 N(3≤N<10000)个运动员,他们的 id 为 0 到 N−1 ,他们的实力由一组整数表示。 他们之间进行比赛,需要决出冠亚军。比赛的规则是 0 号和 1 号比赛,2 号和 3 号比赛,以此类推,每一轮,相邻的运动员进行比赛,获胜的进入下一轮;实力值大的获胜,实力值相等的情况, id 小的情况下获胜;轮空的直接进入下一轮。
输入描述
输入一行 N 个数字代表 N 个运动员的实力值(0<=实力值<=10000000000)。
输出描述
输出冠亚季军的 id ,用空格隔开。
样例1
输入
2 3 4 5
输出
3 1 2
说明
第一轮比赛,
id 为 0 实力值为 2 的运动员和 id 为 1 实力值为 3 的运动员比赛,1 号胜出进入下一轮争夺冠亚军,
id 为 2 的运动员和 id 为 3 的运动员比赛, 3 号胜出进入下一轮争夺冠亚军,
冠亚军比赛,3 号胜 1 号,
故冠军为 3 号,亚军为 1 号,2 号与 0 号,比赛进行季军的争夺, 2 号实力值为 4 ,0 号实力值 2 ,故 2 号胜出,得季军。
冠亚季军为 3 1 2。