Official

B - Near Assignment Editorial by maroonrk_admin


\(A=B\) の場合は明らかに可能なので,それ以外のケースを考えます.

\(K\) の値で場合分けします.

\(K=1\) のケース:

\(A\)の要素をランレングス圧縮した結果を考えると,操作によって”減る”ことはあっても”増える”ことはありません. ここから得られる条件として,\(B\) をランレングス圧縮した結果が \(A\) の部分列である必要があるとわかります. そしてこれは十分です. \(B\) に対応する \(A\) の部分列を伸ばしていく操作を行えば良いからです. これで \(K=1\) のケースは解けました.

\(K \geq 2\) のケース:

操作を逆から見ると,以下のようになります.

  • \(|i-j| \leq K,B_i=B_j\) を満たす \(i,j\) を選び,\(B_i\) を好きな値に変更する.

まず,\(B\) に一度も操作を行えない場合,答えは No です. また,\(B\) に登場するが \(A\) に登場しない値がある場合も答えは No です. 実はこれ以外のケースはすべて Yes です.

\(B_i\) を好きな値にする,という部分を,\(B_i\) をワイルドカード \(*\) に変更するという操作で捉え直しましょう. \(B\)\(1\) 回操作を行うことで,\(*\)\(1\) つ存在する状態にしておきます.

\(*\) を絡めることで,\(B\) の隣接要素の swap が実現できます.

  • \(*x\)\(x*\) にしたい場合: \(*x\)\(xx\) だと思って操作すれば \(x*\) にできる.
  • \(*xy\)\(*yx\) にしたい場合: \(*xy \to yxy \to yx* \to y*x \to *yx\) とすればよい.

以上の操作を組み合わせると,\(B\) の要素の重複をすべて削除し,かつ好きな順序で並べることができます. 特に,\(B\)\(A\) にマッチするようにできます. よって \(A\)\(B\) に変形できるとわかります.

以上の操作をそのまま実装すると \(O(N)\) 解法が得られます. なお,回答例はサボってソートを行っているため \(O(N\log N)\) 解法になっています.

回答例(C++)

posted:
last update: