コンテスト中AC:A〜C
コンテスト後解説なしでE,FをAC。
Dは解説見たが、方針は間違っていなかったが、考慮できていない部分があった。
D - Polynomial division
であるので、
の時、
の時、
として、の順で求められると考えました。
(なお、の時は
としておけば良い)
しかしながら、これはREになっていました。
なぜかというと、の場合があるからでした。
そこで、以下のように考えました。
となる最小の
を
とします。
となるので、以下の方針としました。
の時、
の時、
とします。 しかし、この解法でもREとなり、時間内にACできませんでした。
コンテスト後に考えた結果、実装時に色々と考慮できていなかった部分があったことが原因であり、解法自体は正しいことがわかりました。
以下がACしたコードです。
上の実装に、として、
について、それぞれ
個分の領域を確保する処理がありますが、ここは不要です。
全て個分確保しておけば良いです。逆にこれより少なくとだめです。
なぜなら、のみが保証されているため、
は最大で
になるからです。
また、今回、のインデックスをベースに実装しましたが、
をベースにした方がわかりやすいと思います。
提出コード
E - Wrapping Chocolate
小さいチョコレートから優先して箱に入れる場合、大きい箱に入れると、後々入れられないチョコレートが出てくる可能性があります。そこで、チョコレートを大きいものから順に入れることを考えます。
ここでチョコレートの大小関係を定義しておきます。チョコレートを縦を第一キー、横を第二キーとして降順ソートしたときの基準を適用します。すなわち、番目の
番目のチョコレートについて、
の場合は
番目が大きく、
の場合は
なら
番目が大きい
となります。
まだ箱に入れられていないチョコレートの中で最大のものを番目とします。
まず、縦を考えます。
を満たす箱
に入れることが可能です。ここで、これを満たす箱であれば、どれに入れても、縦の制限によって箱に入れられないチョコレートが発生することはありません。なぜなら、残ったチョコレートの縦は
以下だからです。
次に横を考えます。
横については、を満たす箱
ならどれでもよいというわけにはいきません。なぜなら、残ったチョコレートの横は
以下であるとは限らないからです。
ということから、横はを満たす中で最小のものにしておく必要があります。
以上をまとめると、以下のような貪欲法になります。
1.箱に入っていないチョコレートの中で最大をものを1つ選びチョコレート
とする
2.チョコレートが入っておらず、かつ、チョコレートが入れられる箱の中で、横が最小の箱
を選ぶ
3.チョコレートを箱
に入れる
具体的はアルゴリズムに移ります。
順序付き多重集合にチョコレート
を入れる候補となる箱を記録することにします。
の順序は
の昇順とします。
には、チョコレート
を入れたい時、
を満たす箱
を全て記録します。その中から、
を満たす中で最小の箱
を二分探索によって探し、
から削除します。
なお、に入っている箱は全て
を満たすので、
は記録する必要がなく、
だけ記録しておけばよいです。
これを素直に実装すると、各チョコレートについて、候補となる箱を探すため、集合への追加を除いてもとなり、間に合いません。
そこで以下の方法とします。
まず、チョコレートと箱はそれぞれ縦()を第一キーに、横(
)を第二キーとして降順ソートします。
の時、
なので、
である時、
となります。
そのため、チョコレートで
に追加した箱は、チョコレート
でも追加したままにしておけます。
従って、の順に調べる時、
チョコレート
で
に追加された箱は、チョコレート
でも追加したままにでき、チョコレート
で新たに必要になった箱だけを
に追加すればよくなります。
これにより、箱はに高々1回しか追加されず、全体で
となります。
多重集合としてC++のmultisetを使えば、追加、検索、削除はlog時間でできるので、高速に実現できます。
F - Endless Walk
頂点を出発して、頂点
に帰って来れるような閉路が存在すれば、
に到達後に無限に移動できることが確定します。
ある強連結成分に属する全ての頂点は、この条件を満たします。
よって、強連結成分の集合族をとしたとき、これら強連結成分に属するいずれかの頂点に到達できれば、無限に移動できます。
強連結成分は、強連結成分分解でで得られます。AtCoder Libraryのscc_graphを強連結成分が二次元配列で得られるので、列のサイズが2以上であれば閉路を含み、
とみなせます。
(補足:グラフが単純でなければ、自己ループを考慮する必要があるので、サイズが1でも閉路となります。)
あとは、強連結成分の頂点に到達可能な頂点を調べれば良いですが、以下のように言い換えました。
の有向辺を全て逆向きにしたグラフ
において、強連結成分のいずれかの頂点から到達可能な頂点を調べる
これは強連結成分に属する全ての頂点をキューに入れてBFSを開始すれば良いです。