AtCoder Regular Contest 068:E - Snuke Line

問題

https://atcoder.jp/contests/arc068/tasks/arc068_c

考え方

これは難しい...

考えていたこと

  • imos法で区間を含むか数える、がこれは重複して数えてしまうのでダメ。
  • d を全通り試すことは O(logM) でできるのでこれは全探索

解説見た

公式解説のベースに考えていく。がほぼまんま公式解説の写しみたいになってしまった...

区間の長さ d\ (1 \le d \le M) について考えていることにする。l_i, r_i なる i 番目の区間について区間の長さが d よりも大きい r_i - l_i + 1 \gt d 場合は必ず 1 回以上は訪れることになる。そうでないとき、つまり r_i - l_i + 1 \le d であるときは高々1回のみ訪れることになる。

上記から区間の長さ r_i - l_i + 1 で分類して考えることができて、これが重要な考察である。区間の長さが小さい区間から考えていく。これは各区間について区間の長さで昇順ソートすればよい。

j\ (0 \le j \le M) に含まれる種類の数を cnt_j で表すことにする。

区間の長さが k = r_i - l_i + 1区間 i について k \lt d を満たしているとき l_i \le j \le r_i なる cnt_j1 を加算する。これは BIT などのデータ構造を用いればよい。(区間加算できるように imos 法のような工夫が必要)

このとき cnt_0 + cnt_d + cnt_{2d} + \cdots区間の長さが d 未満の区間に含まれる種類の合計となる。これに、区間の長さが d 以上の区間の個数を足せばよい。

長さ d 未満の区間の数について、区間の長さ d で含まれる場合は d+1 でも必ず含まれるので、それぞれの区間については 1 回見ればよいことがわかる。区間の長さ d でどこまでの区間まで計算したか保持しておけばよい。

よって全体の計算量は O((MlogM + N)logM) となる。


ちなみに d で全探索しても logM になるのは、区間の個数は  \displaystyle \int_1^M \frac{M}{x}dx \approx MlogM 個であるため。調和級数を近似すると log で抑えられるというテク。


ちなみに放送解説も見たが、xy平面の個数をO(logM)で数える手法が難しかった

どこに着目して考察するべきだったか

区間に含まれる名産物は重複する可能性があるので、重複しないように数える工夫が重要。今回の問題の場合、区間の長さで分類することで、「必ず1つ以上含まれる or 含まれるかどうかわからないが高々1つ」の区間に分類できる。「含まれるかどうかわからないが高々1つ」である区間は、長さ d ごとに数えると重複せずに数えることができる。

何がバグっていたか

得た知見(典型ポイント)

  • 重複しないように工夫する(区間の長さで分類 or 区間の左端に着目)
  • 区間 [l, r] を xy 平面にプロット

類題

参考