E - Segment-Tree Optimization Editorial
by
riano_
整数 \(i\) と \(i+1\) の間に「\(i\) 番目の仕切り」があると考えます(先頭に \(0\) 番目、末尾に \(N\) 番目の仕切りがあるとします)。以下では、\(i\) 番目の仕切りを単に仕切り \(i\) と呼びます。題意の二分木を作成したとき、葉でない頂点に、その頂点が持つ区間を子の持つ \(2\) 区間に分ける仕切りを割り当てると、
- \(1\) ~ \(N-1\) までの仕切りが \(1\) 回ずつ登場する
- 各頂点の仕切り \(i\) に対して、子の持つ仕切りは \(i\) より小さいものと \(i\) より大きいものが \(1\) 個以下ずつである
という性質が成り立ちます。
各区間クエリについて考えると、両端の仕切りは \(l-1\) と \(r\) ですが、このクエリで調査される頂点のうち最も深いものは、仕切り \(l-1\) と \(r\) のうち深い方の頂点の子となります。したがって、深さの最大値が \(d\) 以下であるためには、完全二分木上で深さ \(d-1\) 以下の頂点に、クエリで登場する仕切り全て(ただし、\(0\) と \(N\) は除く)を割り当てることができればよいです。そのような頂点は \(2^d-1\) 個あるので、これによって \(d\) が分かります。
続いて、\(c\) を最小化します。深さ \(d\) の頂点が調査されるのは、仕切り \(l-1\) と \(r\) のうちどちらかが深さ \(d-1\) にあった時です。また、クエリごとに、深さ \(d-1\) の仕切りの数の \(2\) 倍だけ深さ \(d\) の頂点が調査されることが分かります。結局、\(c\) は、深さ \(d-1\) の頂点に割り当てられた仕切りの登場回数(今後、重みと呼びます)の総和の倍です。したがって、深さ \(d-1\) までの完全二分木を考え、そこに適切な順序でクエリに登場する仕切りを割り当てたとき、深さ \(d-1\) に割り当てられた重みの総和を最小化すればよいです。
完全二分木上で、深さ \(d-1\) にある仕切りは、深さ \(d-1\) 以下にある仕切り \(2^d-1\) 個を並べた列の中で奇数番目(1-indexed)に位置します。また、深さ \(d-1\) までに配置する必要のある仕切りは一般には \(2^d-1\) 個よりは少ないので、仕切りを割り当てない頂点を配置することもできます(この場合、復元した二分木においてはその位置の頂点が葉となるか、あるいはクエリに登場しない重み \(0\) の仕切りを配置することになります)。
ここで、次のような問題を考えます。
\(s\) 項の数列を、順序を保ったまま \(2^d-1\) 個のマスに割り当て、奇数番目のマスに書かれた数の総和を最小化する(但し \(2^{d-1} \leq s \leq 2^d-1\))
この問題で許される配置方法は、一般には題意の二分木を復元できないものもあります。しかし、最適解においては、空白は奇数番目のマスにしか存在しないため、この場合の配置は必ず題意の二分木に復元することができます(隣接する値の仕切りの間に空白マスがあったとしても、それが奇数番目=考えている範囲で最深の頂点に当たる位置であれば、単に仕切りを持たない葉とすればよいためです)。
したがって、上記の問題を解けばよく、空白を連続させる必要がないことを考えると、数列のうち何項目まで配置したか、および空白をいくつ配置したか、を添え字として持つ DP で解くことができます。
なお、\(d=0\) の場合がコーナーケースとなりうるので注意してください。
【おまけ( \(N\leq 2\times 10^5\) の場合の解法)】
最後の問題は、偶数番目に空白が割り当てられないことから「奇数番目に選ばれる数は \(s-(2^{d-1}-1)\) 個であり、元の数列で隣接しない」ことが分かります。よって、
\(s\) 項の数列の中から、連続しない \(t\) 項を選んで和を最小化してください
という問題と言い換えられるので、以下の問題と同様の要領で解けます。
posted:
last update:
