セグメント木に変なものを乗せる
この記事は、「木 Advent Calendar 2023」の14日目です。
昨日の記事はそすうぽよさんの「木曜日」でした。
明日の記事は箱さんの「なにか書きます」です。
セグメント木
ご存知のとおり、セグメント木は大変便利なデータ構造です。配列と同じようなランダムアクセスによる要素の取得・書換えが
しかし、そんなセグメント木にも大きな欠点があります。それは、要素と二項演算がモノイドの関係になっていなければ、正しい答えを得ることができない、ということです。
そこで、本記事では、変なものふたつについて、セグメント木に乗せたいときにどうすればよいかを show time.
変なものの一覧
10 進数
数字からなる長さ
-
番目の数字をi に置き換える。x\ (0 \le x \le 9) -
番目からl 番目の数字をr 進法表記の数とみなし、10 で割ったあまりを出力する。998244353
直感的には、二項演算として
しかし、これはうまくいきません。
なぜなら、これはモノイドが満たすべき性質である結合律を満たさないからです。
たとえば、
そこで、
こうすればモノイドになります。
括弧列
長さ (
, )
のみからなる文字列に対し、以下の二通りのクエリを処理しなければならない状況を想定してみます。
-
番目の文字をi に置き換える。c\ (c \in \{\texttt{(}, \texttt{)}\}) -
番目からl 番目の文字を括弧列として見たとき、「対応の取れた括弧列」であるか判定する。r
この問題は、以下のようにして解くことができます。
-
(
の値を とする。(0, 1) -
)
の値を とする。(1, 0) - 二項演算を
とする。(a, b) * (c, d) = (a + \max\{c - b, 0\}, \max\{b - c, 0\} + d) - 値が
になる文字列は「対応の取れた括弧列」である。(0, 0)
たとえば、 ()
の値は )(
の値は
Discussion