公式

A - 料理コンテストと食材 / Cooking Contest and Ingredients 解説 by kyopro_friends


初心者の方へ


問題は次の2つのパートに別れます

  • 上位 \(K\) 人を求める
  • 上位 \(K\) 人に共通する得意食材の個数を求める

上位 \(K\) 人を求める

得点と番号の組 \((V_i,i)\) を問題文の指示通り「得点の降順、タイなら番号の昇順」という比較関数でソートすることで上位から順に並べ替えることができます。
この比較関数を実装してもよいですが、\((V_i, -i)\) を降順にソートすることで同じ効果を得ることができます。

今回ように「1つ目の降順、タイなら2つ目の昇順でソート」と昇順と降順が混ざっている場合は、適切に \(-1\) 倍することで、通常の昇順/降順ソートで行うことができます。

上位 \(K\) 人に共通する得意食材の個数を求める

各食材に対して、それが上位 \(K\) 人の得意食材として登場する回数を求めます。登場回数が \(K\) であることが、全員に共通する得意食材であることと同値であるため、そのような食材の個数を求めればよいです。

実装例 (C++)

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

int main(){
  int n, m, k;
  cin >> n >> m >> k;
  vector<int>v(n);
  vector<int>c(n);
  vector<vector<int>>t(n);
  
  for(int i=0; i<n; i++){
    cin >> v[i] >> c[i];
    vector<int>ti(c[i]);
    for(int j=0; j<c[i]; j++) cin >> ti[j];
    t[i] = ti;
  }
  
  // (v[i], -i) を降順ソート
  vector<pair<int,int>>vi(n);
  for(int i=0; i<n; i++) vi[i] = {v[i], -i};
  sort(vi.rbegin(), vi.rend());
  // 食材の登場回数をカウント
  vector<int>count(m+1);
  for(int p=0; p<k; p++){
    int i = - vi[p].second;
    for(int j=0; j<c[i]; j++){
      count[t[i][j]]++;
    }
  }
  
  // 登場回数が K である食材の個数
  int ans = 0;
  for(int i=1; i<=m; i++){
    if(count[i] == k){
      ans++;
    }
  }
  cout << ans << endl;
}

実装例 (Python)

N, M, K = map(int, input().split())
V = []
T = []
for _ in range(N):
  v, c, *t = map(int, input().split())
  V.append(v)
  T.append(t)

# (v[i], -i) を降順ソート
VI = [(V[i], -i) for i in range(N)]
VI.sort(reverse=True)

# 食材の登場回数をカウント
count = [0] * (M+1)
for _, minus_i in VI[:K]:
  i = - minus_i
  for t in T[i]:
    count[t] += 1

# 登場回数が K である食材の個数
print(count.count(K))

投稿日時:
最終更新: