Range Tree のメモ

はしがき

タイトル通りです。可読性は低いです。やる気が出たら可読性を上げます。

todo

point add rectangle sum (https://judge.yosupo.jp/problem/point_add_rectangle_sum)を解きます。

tree.build()

まず、登場する点をすべて先読みし、ソート済みの点列$${P = ((x_1, y_1), \cdots, (x_k, y_k))}$$を作ります。この$${P}$$から$${segx}$$を構築します。$${segx}$$の頂点$${[l, r]}$$に持たせる要素は、$${sorted((x_l, y_l), \cdots, (x_r, y_r))}$$および$${sorted((y_l, x_l), \cdots, (y_r, x_k))}$$です。

また、頂点$${[l, r]}$$に長さ$${r-l+1}$$の$${segy}$$を構築します。$${segy}$$は重みの区間和を求めるために使います。

構築はソートがボトルネックで、たぶん$${O(n\log ^ 2 n)}$$です。

tree.add(x, y, w)

$${P}$$における$${p=pos(x, y)}$$は lower_bound で求められます。

頂点$${[p, p]}$$の上にあるすべての頂点$${[l, r]}$$に対して$${segy}$$の変更を行います。$${sorted((y_l, x_l), \cdots, (y_r, x_k))}$$における$${q=pos(y, x)}$$も lower_bound で求められます。あとは$${segy.add(q, w)}$$をすればよいです。

各$${segy.add(q, w)}$$で$${O(\log n)}$$、頂点$${[p, p]}$$の上にある頂点の個数が$${O(\log n)}$$なので、$${O(\log ^ 2 n)}$$です。

tree.sum(l, r, d, u)

頂点$${[l2, r2]}$$の寄与を考えます。$${intersect([l, r], [l2, r2])=no}$$ならば寄与は$${0}$$です。$${intersect([l, r], [l2, r2])=partial}$$ならば、子の頂点を見ればよいです。$${intersect([l, r], [l2, r2])=overlap}$$ならば頂点$${[l2, r2]}$$の$${segy}$$で寄与を計算します。

overlap している、というのは$${l\le x_{l2}\le x_{r2}\le r}$$という意味です。

これは簡単で、$${sorted((y_l, x_l), \cdots, (y_r, x_k))}$$に対して$${(d, -inf), (u, inf)}$$で lower_bound したものを$${p, q}$$として$${segy.sum(p, q)}$$が寄与になります。

たぶん全体で$${O(\log ^ 2 n)}$$になるはず。

おわり

segtree を 2 個書きます。だるいね。

やる:実装して、実装例を貼る

この記事が気に入ったらサポートをしてみませんか?