セグメント木がモノイドを必要とする理由
はじめに
セグメント木や遅延セグメント木が扱うデータに対しては、抽象的にはモノイドやモノイド作用付きモノイドであること、また作用の準同型性などが要請されます。この記事では具体的な例や計算を通してそれらの性質が要求される構造を確認していきます。
数学的準備
モノイド
集合
- 結合律
の任意の元S に対して、a,b,c (a \cdot b)\cdot c = a \cdot (b \cdot c) - 単位元の存在
の元S が存在して、e の任意の元S に対してa e \cdot a = a \cdot e = a
を満たすならば、組
モノイド作用
-
の任意の元X についてx x@1_M = x -
の任意の元M とa, b の任意の元X に対してx (x@a)@b = x@(a \cdot b)
を満たすもののことをいいます。
準同型
準同型とは、数学的構造(特に代数的構造)を保つような写像のことです。
特に、二つのモノイド
が成り立つような写像のことです。
セグメント木
機能
セグメントツリーは以下のような機能を持ったデータ構造です。
- 代入更新: 任意の値を
で更新することができる\Theta(\log N) - 区間取得: 任意の区間に含まれる値の集約値[1]を
で求めることができる\Theta(\log N)
必要とされる性質
セグメント木の上で扱う値はモノイドであること、すなわち結合律と単位元が存在することを要求されます。
上記性質を要求する背景
- 結合律を要求する理由
結合律は、任意の区間に含まれる値の集約値が一意に定まるために必要です。例えば、集約値を求めたい区間に含まれる値が だった場合、これらの値の積を求める際にx_1, x_2, x_3, x_4 と計算する場合や(x_1 \cdot x_2)\cdot(x_3 \cdot x_4) と計算する場合など色んなパターンが存在しますが、それらの値がすべて等しくなるためには結合律が必要です。(x_1 \cdot (x_2 \cdot x_3))\cdot x_4 - 単位元を要求する理由
単位元は、モノイドの積に対して何も影響を与えない値として利用されます。具体的な例としては、セグメント木の配列から完全二分木を構成する際の埋め草として単位元が利用されます。
遅延セグメント木
機能
- 区間更新: 任意の区間に含まれる値を
で更新することができる\Theta(\log N) - 区間取得: 任意の区間の値の集約値を
で求めることができる\Theta(\log N)
必要とされる性質
遅延セグメント木では集約値を求めるための二分木data
と、区間に対して与える作用を溜めておくための二分木lazy
の二つを利用して計算を行います。この時、data
とlazy
上で扱うデータはそれぞれモノイドである必要があります。ここではdata
上のモノイドをlazy
上のモノイドを
このとき、
すなわち、任意の
が成り立つことが求められます。
遅延セグメント木に載せるデータに要請される性質を数式の形でまとめると以下のようになります。ただし、
- 結合律
(x_1 \cdot x_2) \cdot x_3 = x_1 \cdot (x_2 \cdot x_3) (m_1 \times m_2) \times m_3 = m_1 \times (m_2 \times m_3)
- 準同型性
(x@m_1)@m_2 = x@(m_1 \times m_2) (x_1 \cdot x_2)@m = (x_1@m)\cdot(x_2@m)
準同型性に関しては、余談でもう少し整理を行います。
上記性質を要求する背景
二分木data
上の値がモノイドであることを要求される理由については、セグメント木の場合の説明と全く同様です。
-
二分木
lazy
上の値がモノイドである理由-
結合律を要求する理由
lazy
上のデータの要素(=作用素)の積の結合の順番は遅延セグメント木に与えられる区間更新・区間取得のクエリに依存しますが、同様の効果を与えるクエリの結果を一意にするためには、結合律が必要になります。
具体的に、配列 から生成された遅延セグメント木に次のようなクエリを与えた場合の結果を見てみましょう。[x_1,x_2] - パターンA
-
に[0,2) を作用a \in M -
に[0,2) を作用b \in M -
に[0,2) を作用c \in M -
の集約値を取得[0,1)
-
- パターンB
-
に[0,1) を作用a \in M -
に[0,2) を作用b \in M -
に[0,2) を作用c \in M -
の集約値を取得[0,1)
-
ここで、結合律を仮定せずにA,B両パターンの計算を行うと、Aでは
、Bではx_1@((ab)c) となります。x_1@(a(bc)) 計算過程
この二つの計算結果が一致し、
となるために、x_1@(abc) における積には結合律が必要になります。M - パターンA
-
単位元を要求する理由
モノイド における単位元は、作用を起こさない要素として使用されます。例えば、区間作用のクエリの対象となっていない部分の区間については、(M,\times,1_M) lazy
における対応するノードに単位元を置くようにします。
-
-
準同型性1について
準同型性1は、作用素を合成してから作用させた結果と作用素を一つ一つ作用させる結果が一致するようにするために必要になります。具体例として、配列 から生成した遅延セグメント木の区間[x_1,x_2] に作用素[0,2) を作用させる場合を考えます。a,b \in M 計算過程
このとき、区間
の集約値は[0,2) である一方、区間((x_1x_2)@a)@b の集約値は[0,1) 、区間x_1@(ab) の集約値は[1,2) であり、これらの積は準同型性2を用いて、x_2@(ab) (x_1@(ab))(x_2@(ab)) = (x_1x_2)@(ab) と書くことができます。区間
の集約値と区間[0,1) の集約値の積[1,2) と区間(x_1x_2)@(ab) の集約値[0,2) は同一の値でなければいけないので、準同型性1が必要であることがわかります。((x_1x_2)@a)@b -
準同型性2について
作用素を区間に適用させる時に、複数の区間に分割して作用させることを許すために準同型性2が必要になります。具体的な例として、配列 に対して区間[x_1,x_2] と区間[0,1) に分けてそれぞれに[1,2) を作用させたパターンAと、区間a \in M にまとめて[0,2) を作用させたパターンBを考えます。a \in M 計算過程
区間
の集約値はパターンAでは[0,2) 、パターンBでは(x_1@a)(x_2@a) となりますが、これらの値は一致することが期待されており、そのためには準同型性2が必要になります。(x_1x_2)@a
余談
準同型性についての整理
準同型性1,2(特に1)はぱっと見だと準同型の定義と形が違うように見えるので、より準同型らしく見えるように変形を行いたいと思います。
いま、モノイド
のように
-
準同型性2
準同型性2の式を
を用いて書き直すとf_m f_m(x \cdot y) = f_m(x)\cdot f_m(y) となり、準同型性2の式が準同型性、より特殊には自己準同型性を表していることがわかると思います。
-
準同型性1
また、準同型性1の式について
を用いて書き直すと、f \begin{align*} f(m_1\times m_2)(x) &= f(m_2)(f(m_1)(x)) \\ &= (f(m_2) \circ f(m_1))(x) \\ \iff f(m_1\times m_2) &= f(m_2) \circ f(m_1) \end{align*} となります。ここで、
を写像\circ' に対して、f,g となるような演算として定義するとg\circ' f \coloneqq f\circ g f(m_1\times m_2) = f(m_1) \circ' f(m_2) であり、写像
はモノイドf: M \rightarrow \operatorname{Hom}(X,X) からモノイド(M,\times,1_M) [2]への準同型であることがわかります。(\operatorname{Hom}(X,X), \circ', f_{1_M})
十分性
この記事では、モノイドや準同型性がセグメント木・遅延セグメント木の計算に必要であるということを示しましたが、逆にそれらの性質があればセグメント木・遅延セグメント木の計算を行うのに十分であるということには触れていません。よかったら証明してみてください。
付録
付録として、Rustでモノイドを明示的に利用して遅延セグメント木を実装し、典型90問の第29問 Long Bricksを解いたコードを置いておきます。
Discussion