ebisukeプログラミング初心者脱出黙示録

30歳を過ぎてから始めたプログラミングと競プロの記録。Pythonで取り組んでいます。Arduinoで電子工作も

AtCoder-ABC188 C - ABC Tournament【Python解答例】

AtCoder Beginner Contest188に出場してACをとれたC問題の解答例を書いていきます。
AtCoder Beginner Contest 188 - AtCoder


AtCoder Beginner Contest188 C - ABC Tournament

C - ABC Tournament

問題文

選手 1 から選手 2^N までの 2^N 人の選手がトーナメント形式のプログラミング対決をします。
選手 i のレートは Ai です。どの 2 人の選手のレートも異なり、2 人の選手が対戦すると常にレートが高い方が勝ちます。
トーナメント表は完全二分木の形をしています。
より正確には、このトーナメントは以下の要領で行われます。i=1,2,3,…,N について順に、以下のことが行われる。
各整数 j(1≤j≤2^{n-1}) について、まだ負けたことのない選手のうち、 2j−1 番目に番号の小さい選手と 2j番目に番号の小さい選手が対戦する。
準優勝する、すなわち最後に行われる対戦において負ける選手の番号を求めてください。

制約

・1≤N≤16
・1≤A_{i}10^9
・Ai は相異なる
・入力に含まれる値は全て整数である

解答例

n = int(input())

A = list(map(int, input().split()))

score1 = 0 # ブロック1を勝ち上がる人のレート
num1 = 0 # ブロック1を勝ち上がる人の番号
score2 = 0 # ブロック2を勝ち上がる人のレート
num2 = 0 # ブロック2を勝ち上がる人の番号

for i in range(2**n // 2): # ひとつのループで2つのブロックを判定するため範囲は全選手2^nの半分)
    if score1 < A[i]:
        score1 = A[i]
        num1 = i+1 # 出力しやすいようにi に1を足す
    if score2 < A[i + 2**n //2]:
        score2 = A[i + 2**n //2]
        num2 = i+1 + 2**n //2

if score1 < score2:
    print(num1)
else:
    print(num2)

解説

2^N 人のトーナメントの準優勝者(の番号)を求める問題です。

勝戦であたる2人は2つのブロックを勝ち上がります。
まず、2つのブロックのレートの高い人を求めました。

ループは選手数2^nの半分を範囲としました。
1つ目のブロックの最高得点を求めるため、score1変数よりレートが高い人がいれば代入していきます。
最高得点の人の番号は出力時に楽をするためi+1としました。
iに2^n/2だけ足せば2つ目のブロックの選手も同時に判定できます。

このループを抜けたとにscore1とscore2を比較して弱いほうの番号を出力すればOKです。




今回もC問題まで解くことができました。
D問題が解けず足踏みが続いています。
正直 歯がゆいですが投げ出さず続けていきたいです。

コンテストでは解けませんでしたがD問題の解説をみて記事にしたいと思います。


ABC188の関連記事はこちら
ebisuke33.hatenablog.com
ebisuke33.hatenablog.com