Official

H - 3 枚階段 / Discarding Triplets Editorial by KoD


\(x, x+1, x+2\) が書かれたカードが存在するような整数 \(x\) であって、最小のものをとります。最終的に \(x\) が捨てられないならば、\(x+1, x+2\) のいずれか片方は必ず捨てられているとしてよいです。\(x+1\) が捨てられているならば、\(x+1, x+2, x+3\) が書かれたカードが一回の操作で捨てられたことになるので、この操作を取りやめ、\(x, x+1, x+2\) を代わりに捨てても最後に残るカードの数は変わりません。\(x+1\) が捨てられず、\(x+2\) が捨てられた場合は、\(x+2,x+3,x+4\) を捨てる操作を取りやめて \(x, x+1, x+2\) を代わりに捨ててもよいです。

よって、このような \(x\) に対し、\(x, x+1, x+2\) が書かれたカードを捨てる操作を必ず行うとしてよいです。以上から、

  • 残っているカードに書かれた数の最小値を \(x\) とする
  • \(x, x+1, x+2\) が書かれたカードが存在するか調べる。存在するならそれらをまとめて捨て、存在しないなら \(x\) は操作後に残るカードとして数える

という操作を繰り返し行うことでこの問題を解くことができます。

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

int main() {
    int n;
    cin >> n;
    multiset<long long> a;
    while (n--) {
        long long x;
        cin >> x;
        a.insert(x);
    }
    int ans = 0;
    while (!a.empty()) {
        const long long x = *a.begin();
        a.erase(a.begin());
        if (a.find(x + 1) != a.end() and a.find(x + 2) != a.end()) {
            a.erase(a.find(x + 1));
            a.erase(a.find(x + 2));
        } else {
            ans += 1;
        }
    }
    cout << ans << '\n';
    return 0;
}

posted:
last update: