連想配列の良い練習問題!
問題概要
正の整数からなる数列が良い数列であるとは、数列に含まれる任意の整数値 について、数列中に
がちょうど
個含まれていることをいう。
与えられた数列 に対して、いくつかの要素を削除することで、よい数列となるようにしたい。削除すべき要素数の最小値を求めよ。
制約
考えたこと
数列の数の並びは全く関係なくて、「どの数値が何個あるか」だけが重要。なので、まずは集計処理をしよう。次のような連想配列 (C++ ならば map 型) を構築する。
nums[v]:数列に含まれる整数値
の個数
そうしたあとは、値 ごとに考えていこう。次のようにすればよい。(答えを表す変数を
res とする)
nums[v] >= vのとき:値を
nums[v] - v個削除すれば、数列中にが
個含まれる状態になる
- つまり、
res += nums[v] - vとする
- つまり、
nums[v] < vのとき:この場合は値をすべて削除するしかない
- つまり、
res += nums[v]とする
- つまり、
この解法の計算量は となる。
コード
#include <bits/stdc++.h> using namespace std; int main() { long long N, a; cin >> N; map<long long, long long> nums; for (int i = 0; i < N; i++) { cin >> a; nums[a]++; } long long res = 0; for (auto [val, num] : nums) { if (num < val) res += num; else res += (num - val); } cout << res << endl; }