AtCoder practice contest B問題 Interactive Sorting

スナネコです。
AtCoderpractice contestのB問題を解いたので解説を書きます。

問題ページにあるコード例を読むとわかりますが、この問題は「Q回以下の比較で、長さNの数列をソートせよ」と読み替えられます。

(N,Q)=(26,1000)のとき

コード例に書いてあるとおり、バブルソートなど、O(N^2)のソートアルゴリズムを実装すると通ります。
(26,100)のアルゴリズムでも当然解けるので、(26,100)が解けるなら、(26,1000)のためのコードを書く必要はありません。

(N,Q)=(26,100)のとき

最悪計算量がO(N\log N)のソートアルゴリズムを書く必要があり、定数倍にも気をつける必要があります。
マージソートをすると、99回の比較でソートできることが証明できます。

(N,Q)=(5,7)のとき

本題です。
7回の質問で得られる情報7bit128パターンから、ありえる数列の並び5!=120通りを特定する必要があります。
この厳しすぎる条件から、毎回の質問は返答がほぼ半々に分かれるようにするしかないことがわかるので、何を質問すればいいか選択肢が絞れます。

1回目

(A,B)を質問し、A<Bと返ってきたとしてよいです。残りの可能性は60通りです。

2回目

質問として(A,C) か (C,D)のどちらかが考えられます。
(例えば(B,C)は数列全体を反転すれば(A,C)と同じですし、(C,E)はDとEを入れ替えれば(C,D)と同じです)
(A,C)を聞いてA<Cと返ってきた場合、ありえる数列が40通り残るので、残りの5回で判別できません。
なので(C,D)を聞きます。C<Dとしてよいです。残りの可能性は30通りです。

3回目

質問として(A,C)、(A,D)、(A,E)の3通りが考えられます。
(A,D)を聞いてA<Dと返ってきた場合、ありえる数列が25通り残るので、残り4回で判別できません。
(A,E)を聞いてA<Eと返ってきた場合、ありえる数列が20通り残るので、残り4回で判別できません。
なので(A,C)を聞きます。A<Cとしてよいです。残りの可能性は15通りです。

4回目

現時点でA<C<D、A<Bがわかっています。ABCDの並び順はABCD,ACBD,ACDBのどれかで、さらにEがどこに入るかで3×5の15通りの可能性があります。
意味のある質問と、最悪ケースを考えると
A>E 12通り
B>C 10通り
B<D 10通り
B>E 9通り
C<E 8通り
D>E 11通り
となるので、(C,E)と質問するしかないことがわかります。

4回目でC<Eになったとき

A<C<(D,E) かつ A<Bがわかっています。DEの順序を確定するのに1回、Bの位置4通りを確定するのに2回の計3回で特定できます。

4回目でC>Eになったとき

意味のある質問と、最悪ケースを考えると
A<E 4通り
B>C 4通り
B>D 5通り
となるので、(A,E) か (B,C)を質問すればよいです。どちらでもあと2回の質問で特定できますが、(B,C)の方があとが簡単です

5回目でB<Cになったとき

A<B<C<D、E<Cがわかっているので、Eがどこに入るか3通りを2回で確定できます

5回目でB>Cになったとき

(A,E)<C<(B,D) となるので、AE,BDの順序をそれぞれ2回で特定すれば良いです。


以上でこの問題が解けました。
最後の何回かの質問の部分の場合分けがちょっと大変ですが、他に選択肢はないので、頑張って場合分けを実装するしかなさそうです。