Official

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\) 項を選んで和を最小化してください

という問題と言い換えられるので、以下の問題と同様の要領で解けます。

https://atcoder.jp/contests/abc218/tasks/abc218_h

posted:
last update: