Ex - Multiply or Divide by 2 Editorial by tatyam


問題文の操作は、\(x\)\(1\) ビット右にシフトする操作と、 \(1\) ビット左にシフトする操作に対応します。

\(a \in A\) に何度か操作を行って \(b \in B\) に変換するとき、右シフトで \(a\) の下位ビットの \(1\) を ( \(0\) 個以上) 削ってから、左シフトまたは右シフトで \(b\) に合わせることになります。
すなわち、すべての右シフトを行ってから、すべての左シフトを行うとして良いです。

ここで、左シフトの逆操作を考えてみましょう。

  • \(B\) に含まれている 偶数\(1\) つ選び、\(x\) とする。\(B\) から \(x\)\(1\) つ削除し、代わりに \(\frac x2\)\(1\) つ追加する。

左シフトの逆操作と右シフトは、どちらも数を減らす効果があるので、以下の方法で操作回数を最小化できます。

以下を \(A\)\(B\) が空になるまで行う。

  • \(\max(A) = \max(B) = x\) ならば、\(A\) に含まれる \(1\) つの \(x\)\(B\) に含まれる \(1\) つの \(x\) を対応させ、それらを取り除く。
  • \(x = \max(A) > \max(B)\) ならば、\(A\) に含まれる \(x\) に右シフトを行う。
  • \(\max(A) < \max(B) = x\) ならば、\(B\) に含まれる \(x\) に左シフトの逆操作を行う。(行えない場合は -1 )

\(A, B\) を優先度付きキューで管理すれば、\(a_i, b_i ≤ \text{MAX}\) として、この問題を \(O(N \log N\log \text{MAX})\) 時間で解くことができます。

posted:
last update: