半分全列挙 ( F - Programming Contest )を O(2 ^ (n / 2))で解く
解説
一般的に有名な半分全列挙はソートをする関係でになりがちですが、で解けるよという話をします。
まず、マージソートなどで有名な話として、ソートされた二つの列をソートされた状態でmergeするのはでできます。
C++ですと、std::merge
という標準ライブラリがあるので使うのが手っ取り早いです。
さて、ここまでくるとあとはそこまで難しくないです。
半分に分けた列について考えましょう。
を番目の要素まで、パターンが昇順に入った列とします。
ここで番目の要素をに加えた集合をとすると、このは昇順です。
二つの列を昇順した状態でmergeするのは上述したとおり、線形でできます。
あとはこれの計算量ですが、
です。
よって後は尺取りをすれば、で解くことができました!