Official

C - Final Day Editorial by KoD


\(i\) 番目の生徒が \(4\) 日目終了時点で上位 \(K\) 位に入っている可能性があることは、\(4\) 日目の試験において \(i\) 番目の生徒が \(300\) 点、他の生徒が \(0\) 点をとったときに \(i\) 番目の生徒が上位 \(K\) 位に入っていることと同値です。

\(i\) 番目の生徒の \(3\) 日目終了時点での合計点を\(S_i\) とおきます。 また、\(S_1, \dots, S_N\) のうち \(K\) 番目に大きいものを \(T\) とおきます。\(S_i + 300 \geq T\) なら \(i\) 番目の生徒に対する答えは Yes であり、そうでなければ No です。

実装例 (C++) :

#include <bits/stdc++.h>
using namespace std;

int main() {
    int n, k;
    cin >> n >> k;
    k -= 1;
    vector<int> p(n);
    for (int& x : p) {
        int a, b, c;
        cin >> a >> b >> c;
        x = a + b + c;
    }
    vector<int> q = p;
    sort(begin(q), end(q), greater<>());
    for (int x : p) {
        cout << (x + 300 >= q[k] ? "Yes" : "No") << '\n';
    }
}

実装例 (Python) :

n, k = map(int, input().split())
s = [0] * n;
for i in range(n):
  s[i] = sum(map(int, input().split()))
t = sorted(s, reverse=True)[k - 1];
for x in s:
  print("Yes" if x + 300 >= t else "No")

上記のコードは、大きい方から \(K\) 番目の値を求めるために配列をソートしているので、最悪計算量は \(\Theta (N \log N)\) です。しかし、選択アルゴリズムを用いることで、計算量を \(O(N)\) に落とすことができます。

C++ であれば、std::nth_element を使うことができます :

#include <bits/stdc++.h>
using namespace std;

int main() {
    int n, k;
    cin >> n >> k;
    k -= 1;
    vector<int> p(n);
    for (int& x : p) {
        int a, b, c;
        cin >> a >> b >> c;
        x = a + b + c;
    }
    vector<int> q = p;
    nth_element(begin(q), begin(q) + k, end(q), greater<>());
    for (int x : p) {
        cout << (x + 300 >= q[k] ? "Yes" : "No") << '\n';
    }
}

posted:
last update: