【C#】ABC444 C問題のみ備忘録

記事内に広告が含まれています。

愚直に有り得る組み合わせを試していったらMLE(メモリ制限超過)した。愚直過ぎた。悔しい。

解説

制約と問題の性質上、有り得るパターンを分けていけば探索の必要なくACできる。

2つより多く分かれることを考えなくてよく、分かれなかったものが存在する場合はAの中で最も大きい要素がLとなるはず。となれば昇順に並び替えても問題がない。

考慮すべきは「全て分かれた場合」と「分かれなかったものが存在する場合」の2通りのみ。

全て分かれた場合であれば偶数本になり、A1+An, A2+An-1… と足していってそれがLになる。

分かれなかったものが存在する場合であればL=Anとなるのでそれを省き、残ったもので「全て分かれた場合」と同様の手順を適用できる。

答えは昇順で出力しなければならないが、同じAを使って場合分けをする都合上、Lとなり得る2通りであるAnとA1+Anでは「An<A1+An」以外の状況は考えられないので「分かれなかったものが存在する場合」→「全て分かれた場合」と出力するだけでよい。

そして、制約上どちらかが必ず答えとなるのでこの2通り以外を考慮する必要がないこともわかる。

感想

コンテスト終了後にだいぶ時間を掛けて解説を頭にぶち込んだ。

公式解説や解説放送のコードだと「全て分かれた場合」と「分かれなかったものが存在する場合」の2通りのみを考えて合致しないパターンをはじくように実装していたが、あり得るパターンをこれでちゃんと網羅出来ているのかを理解するのに苦戦した。実力が足りていない。

「全て分かれた」「分かれなかったものが存在する」の場合、これを順にX,Yとして同じAの配列を用いて考えると答えとなるLは必ずY<Xの関係になり、その上でどちらかが存在するか、両方が存在する場合のみ。どちらも存在しない場合は制約上考えなくてよい。

制約を踏まえると賢いコードだけど、特に入力例2みたいな「全て分かれなかった場合」はかなりグレーな通り方をしているように思える。公式解説のコード見て「それで通るの……?」ってなった。

で、公式解説の入力例2は実は「分かれなかったものが存在する」パターンに含まれる。

こちらでは全て割れた結果偶数になる必要があるが、手順通り分かれなかったものを省くと残りは0、つまり偶数になる。要素数が0になると残りの分かれた分を考慮する必要が無いので、初めに置いたL=Anがそのまま答えとして出力できる。

要約すると、とにかく制約に気を付けること。あと求める答えであるLが実質2通りだけになることが肝。答えが3通りかと思ったら、2通りでした~。チクショ~!!!!

コメント

タイトルとURLをコピーしました