Official

C - Combine to Make Non-decreasing Editorial by camypaper


いくつかの区間に分割し、それぞれの区間のビットごとの論理和を取った値が広義単調増加にする必要があるときの区間の個数をできるかぎり大きくしたいという問題です。

\(\mathrm{ dp}_{i,x}\)\(a\) の先頭 \(i\) 番目が現在着目している区間の左端で直前の区間のビットごとの論理和を取った値が \(x\) であるようにするときの最大の区間の個数、とします。
これを愚直にDPすると \(O(N^2)\) 程度かかってしまうため改善が必要です。

\(f(l,r) = a_l \ \mathrm{OR} \cdots \ \mathrm{OR} \ a_r\) とします。
\(r\) を固定すると \(l_1 \le l < l_2\) を満たすときに限り、\(f(l,r)\) の値が \(x\) となる、というような区間 \([l_1, l_2)\)\( \log( \max(a_i))\) 個程度得られます。

これら \(N \log( \max(a_i))\) 個の区間を \(f(l,r)\) の値の昇順に並べ、\(f(l,r)\) の値が同じ場合は \(r\) が小さい方が先に来るようタイブレークを行います。
\(f(l,r)\) の値の昇順に並べたことから、\(\mathrm{ dp}_{i,x}\)\(x\) の部分を落とすことができます。

\(l_1 \leq l < l_2\) を満たす \(l\) について \(\mathrm{ dp}_{r+1}\)\(\max(\mathrm{ dp}_{r+1}, \mathrm{ dp}_{l}+1)\) の大きい方で置き換えるという遷移を行うことで答えを求めることができます。 これはRMQなのでセグメント木を用いることで \(O(\log N)\) で求められます。

\(N \log( \max(a_i))\log N)\) 程度で答えを求めることができ、十分高速です。

posted:
last update: