E - Gap Swap (hard) 解説
by
milkcoffee
\(P\) の転倒数を \(\text{inv}(P)\)、\(\text{sum}(P)=\sum_{i=1}^{N}|i-P_i|\) とします。答えは \(\text{sum}(P)-\text{inv}(P)\) です。以下これを示します。
以下、\(f(P)=\text{sum}(P)-\text{inv}(P)\) とします。
まず、\(P_r=r\) である要素を削除し、位置と値のうち \(r\) より大きいものをそれぞれ \(1\) ずつ小さくして、\((1,2,\ldots,N-1)\) の順列として見直しても \(f(P)\) は変わりません。削除した固定点をまたぐ要素については \(|i-P_i|\) が \(1\) 減り、その固定点との転倒も \(1\) 個消えます。それ以外は変わらないため、\(\text{sum}(P)\) と \(\text{inv}(P)\) の減少量が一致します。
コスト和の下界が \(f(P)\) であることを示します。
操作で選んだ \(2\) 点の間にある固定点を削除して考えると、その操作は隣接 swap と見なせます。隣接する \(a=P_i,\ b=P_{i+1}\) を swap すると、\(\text{sum}(P)\) の変化量は \(-2,0,2\) のいずれかであり、転倒数は \(a<b\) なら \(1\) 増え、\(a>b\) なら \(1\) 減ります。\(\text{sum}(P)\) が \(2\) 減るのは \(a>i,\ b<i+1\) のときだけで、このとき必ず \(a>b\) なので転倒数も \(1\) 減ります。したがって、\(1\) 回の操作で \(f(P)\) は高々 \(1\) しか減りません。昇順のとき \(f(P)=0\) なので、必要なコスト和は \(f(P)\) 以上です。
\(P_i=i\) である位置を操作対象に選べるとしても同様です。上では固定点を削除して考えましたが、仮に削除した固定点を残してそれらを操作対象に使ったとしても、同じ議論により \(f(P)\) を \(1\) 回で \(2\) 以上減らすことはできません。
上で示した下界が達成可能であることを示します。
\(P\) が昇順でないとき、\(f(P)\) をちょうど \(1\) 減らす操作が常に存在します。\(P_k\neq k\) となる \(k\) を小さい順に \(v_1,v_2,\ldots,v_t\) とします。\(P_{v_1}>v_1\) かつ \(P_{v_t}<v_t\) が成り立つため、\(P_{v_i}>v_i\) かつ \(P_{v_{i+1}}<v_{i+1}\) を満たす隣り合う \(v_i,v_{i+1}\) が必ず存在します。
この \(v_i,v_{i+1}\) の間にある要素は全て固定点なので、この \(2\) 点を選ぶ操作は可能です。固定点を削除して見ると、これは \(P_i>i,\ P_{i+1}<i+1\) を満たす隣接 swap です。よって \(\text{sum}(P)\) が \(2\) 減り、転倒数が \(1\) 減るため、\(f(P)\) はちょうど \(1\) 減ります。
これを繰り返せば、\(f(P)\) 回の操作で昇順にできます。以上より最小コストは \(f(P)=\text{sum}(P)-\text{inv}(P)\) です。
あとは初期状態の \(\text{sum}(P)\) と \(\text{inv}(P)\) を求めればよいです。\(\text{sum}(P)\) は \(O(N)\)、\(\text{inv}(P)\) は Fenwick Tree などで \(O(N\log N)\) で求められます。
全体の計算量は \(O(N\log N)\) です。
投稿日時:
最終更新:
