CodeForces#162 Div1-E

65bd3434deeeb8afc00485cdfc3e260a?s=47 snuke
January 20, 2013

CodeForces#162 Div1-E

CodeForces#162 Div1-E の解説

65bd3434deeeb8afc00485cdfc3e260a?s=128

snuke

January 20, 2013
Tweet

Transcript

  1. CodeForces #162 Div1-E RodeSideTrees writer: snuke

  2. ໰୊֓ཁ 東西の道にそって木を植えたり切ったりするクエリ を処理し、各クエリ後に西→東方向のLISを求める 木は各クエリ前に1m ずつ伸びる 植える木の高さは10m 以下 切り倒す木は西から10本目以内 木の本数 N

    ≦ 10^5, クエリ数 M ≦ 2*10^5
  3. ۪௚ͳղ๏ 毎回 LIS を求める。 O(M N log N)となり、さすがに間に合わない。

  4. ૝ఆղ まず、木の成長を無視するために、 t 個目のクエリの時に植えられる木の高さを h から h-t に変換しておきます。 んで、木の(場所,高さ)を x-y平面上にぷろっとしてみる。

  5. ૝ఆղ ߴ͞ ৔ॴ こんな感じ? すると・・・

  6. ૝ఆղ 常に右上方向に辿る最長経路がLISになってる! この場合、LISは赤いやつになります。 LISの普通の条件「hi < hi+1 」と暗黙の条件「xi < xi+1 」からくる特性

    ߴ͞ ৔ॴ
  7. ૝ఆղ さて、この問題におけるクエリは 下から10番目以内に木を追加 左から10番目以内の木を削除 と言い換えられます。 ߴ͞ ৔ॴ

  8. ૝ఆղ とりあえず、各木に Longest Decreasing Subsequence の長さを記録することにしてみます。 図の木のところに LDS の長さを書き込んでみる。 木iの右上の領域中の最大値

    + 1 が 木iのところに書き込まれるシステムらしい。 ߴ͞ ৔ॴ 1 1 1 2 2 3 4
  9. ૝ఆղ 各クエリを爆速で処理する方法を考えてみよう。 ある木の LDS には右上の領域にある木のみが影響を及ぼし、 左 or 下 にある木は影響を及ぼさないことを利用しよう。 ߴ͞

    ৔ॴ 1 1 1 2 2 3 4
  10. ૝ఆղ 植えるクエリ (下から10番目以内に木を追加) 植える木よりも低い木をいったん抜いて、 順番に植え直す。 ߴ͞ ৔ॴ 1 1 1

    2 2 3 4
  11. ૝ఆղ 切るクエリ (左から10番目以内の木を削除) 切る木よりも左の木をいったん抜いて、 切る木以外を順番に植え直す。 ߴ͞ ৔ॴ 1 1 1

    2 2 3 4
  12. ૝ఆղ さて、ここで必要になるデータ構造はなんでしょう? 2次元segtree? → 更新にO(log^2 N)かかり、しかも定数項重そうな   ので多分TLEします。 ߴ͞ ৔ॴ

    1 1 1 2 2 3 4
  13. ૝ఆղ 植えるクエリの時には x 方向の1次元segtree 切るクエリの時には y 方向の1次元segtree だけしか必要ない! O(log N)しかも定数項軽め!

    ※ただし、ノードの更新は両方のsegtreeに適応しないといけません。 ߴ͞(y) ৔ॴ (x) 1 1 1 2 2 3 4
  14. O(N * 10 * log N) くらい ܭࢉྔ

  15. 作問するにあたってLISとちょっと 仲良くなれた気がする。 ご清聴(?)ありがとうございました! CF#162へのご参加ありがとうございました! ·ͱΊ ←twitter(@the_nikaidoes)ͷΞΠίϯ