公式

C - シード番号の割り当て / Seed Number Assignment 解説 by MMNMM


整数の組 \((A _ i+B _ i,i)\) を \(i=1,2,\ldots,N\) それぞれについて求め、これを第一成分は降順に、第一成分が等しい要素については第二成分の昇順にソートすることなどで、「シード番号の優先順位が \(j\) 番目となる参加者の番号」を得ることができます。 あとは、これの逆順列を求め、合計スコアで場合分けをすることでこの問題を解くことができます。

ソートがボトルネックとなり、時間計算量は \(O(N\log N)\) などとなります。

実装例は以下のようになります。

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int main() {
    int N, K;
    cin >> N >> K;

    vector<int> total_score(N);
    for (int& t : total_score) {
        int A, B;
        cin >> A >> B;
        t = A + B;
    }

    // シード番号の優先順位が i 番目の参加者が rank[i] 番の参加者になるようにする
    vector<int> rank(N);
    for (int i = 0; i < N; ++i) {
        rank[i] = i;
    }
    // 合計スコアでソート
    ranges::stable_sort(rank, greater{}, [&total_score](int i) { return total_score[i]; });

    vector ans(N, -1);
    for (int i = 0; i < N; ++i) {
        // 合計スコアで場合分け
        if (total_score[rank[i]] >= K) {
            ans[rank[i]] = i + 1;
        } else {
            break;
        }
    }

    for (int i = 0; i < N; ++i) {
        cout << ans[i] << endl;
    }
    return 0;
}
N, K = map(int, input().split())

total_score = [sum(map(int, input().split())) for i in range(N)]

# シード番号の優先順位が i 番目の参加者が rank[i] 番の参加者になるようにする
rank = [i for i in range(N)]
rank.sort(key=lambda i: -total_score[i]) # 合計スコアでソート

ans = [-1 for i in range(N)]
for i, r in enumerate(rank):
    # 合計スコアで場合分け
    if total_score[r] >= K:
        ans[r] = i + 1
    else:
        break

for a in ans:
    print(a)