仕事をしよう!
概要
はじめ頂点が1つだけの木がある。
その後3種類のクエリが飛んでくる。
1つ目はその木に1つ頂点を追加して、既存の頂点と1本の辺で結ぶもの。
2つ目はある辺のコストを変更するもの。
3つ目はある頂点から最も遠い頂点を求めるもの。
これがたくさん与えられるのでこれを処理する。
部分点1
普通にDFSなどをしてクエリを処理していく。
最悪DFSをN回するのでO(N^2)
満点解法
動的木・・・知らない子ですねえ
Heavy Light Decomposition・・・本命
ただし、これを動的にやるとやばいのでクエリ先読みをする。
具体的にははじめに都市をすべて作ってそれをコスト0の道でつないでおく。
そして都市が新しくできたときには道のコストを変えるだけでよい。
満点解法
この場合に求められる機能は
・ある1辺のコストを変更する。
・ある頂点から最も遠い頂点への距離を求める。
である。
これを実現するためには各頂点について、自分の子で自分と同じブロックに
含まれていないものの孫のうち最も自分から遠いものへの距離が高速に分か
り、かつ自分と同じブロックの頂点の孫で自分からの距離が最も遠いものへ
の距離が高速に分かればよい。そして前者はRMQのようなもの、後者は
BIT+SegTreeで実装できる。
満点解法
図にすると
ブロック
BIT+SegTreeで管理
RMQで管理 RMQで管理 RMQで管理 RMQで管理
満点解法
そして、更新のクエリが来たときははじめのブロックだけBIT、SegTreeを
書き換え、それから根のほうへ向かいつつRMQとSegTreeを更新していく。
また、最も遠い頂点を求めるクエリが来たときは根のほうに向かいながら
RMQとBIT+SegTreeを見て答えを求めていく。
満点解法
それぞれのブロックでの計算量・・・O(log N)
1回のクエリで訪れるブロックの数・・・O(log N)
よって全体の計算量はO(N log^2 N)となる。
お詫び
説明が雑で申し訳ありません。
もしかしたらソースコードを見たほうが雰囲気がつかめるかもしれません。

仕事をしよう!