個人的に勉強したことを整理します。
新規性とか強い主張とかは、特にありません。
Euler Tour
(1) DFS 順に探索して、通った頂点の列を記録する(
(2) 各頂点
参考:
・アリ本 p. 294 (Euler Tour の名前は出ていませんが)Euler Tour による LCA の計算。
登場する頂点を並べますが、計算で必要になるのはむしろ、
通った辺を並べてみる
アリ本の解説と同様、「通った頂点を順に並べます」というのが Euler Tour の基本だと思っていました。ブログ記事を検索しても、この説明の方が多いように思います(ただし探すと、以下に述べる、辺を基礎とした解説も複数存在しました)。 頂点
辺
※ 頂点を並べる説明でも同一の in, out のテーブルが作られるため、特に新しいことをやっている・新しいものが計算できるというわけではないです。
ただ個人的に、こちらの方が分かりやすいなと感じました。
まず、綺麗です。全ての辺が双方向に
「通った辺を並べたもの」から「通った頂点を並べたもの」を復元するのは簡単で、各辺の終点を対応させると変換できます(辺
クエリ各種
部分木クエリ
全ての頂点(辺)が値を持っているとします。頂点
頂点
例えば空欄を単位元として Segment 木 を使えば、値の 1点変更・部分木取得ができます。同じことですが、遅延伝搬 Segment 木 を使えば、部分木更新にも対応できるでしょう。群であれば累積和あるいは Fenwick Tree で置き換えることも可能かもしれません。
見れば分かるように、このように index を持つと、配列の半分しか使いません。「下向きの辺に対してのみ値を持たせます」と言ったばかりでしたから、下向きの移動だけ使って配列を小さくすることができます。beet さんの記事では、頂点属性の Euler Tour と呼び分けています。私は不勉強ゆえ、実装したことがなかったです。
パスクエリ
根からある頂点
各時点で、累積和と計算対象が一致するようにします。群に値を持つ(逆元がとれる)場合にこれが可能です。可換性は要求しません。親 → 子 順の和が手に入ります(適切にやれば 子 → 親 順もできる)。
LCA
アリ本にあるので有名だと思いますが、これが最も発想しにくい Euler Tour の利用方法な気がします。
「両方の頂点を含む極小な部分木」と思うといまいちで、「
ただし以下を見たときには、「両方の頂点を含む極小な部分木」 という見方も知っておくと役に立つなあと感じました。
「全ての頂点を含む部分木」は、「全ての頂点を含む区間」と言い換えられるので、 「