@@ -3,6 +3,22 @@ const math = std.math;
33const Allocator = std .mem .Allocator ;
44const assert = std .debug .assert ;
55
6+ /// Lazy Segment Tree
7+ ///
8+ /// This is a wrapper around a tree of element type S, update operation op, identity e,
9+ /// mapping type F, mapping function, composition function, and identity id.
10+ ///
11+ /// The following should be defined.
12+ ///
13+ /// - The type `S` of the monoid
14+ /// - The binary operation `op: fn (S, S) S`
15+ /// - The identity element `e: fn () S`
16+ /// - The type `F` of the map
17+ /// - The function `mapping: fn (F, S) S` that returns $f(x)$
18+ /// - The function `composition: fn (F, F) F` that returns $f \circ g$
19+ /// - The function `id: fn () F` that returns `\mathrm{id}`
20+ ///
21+ /// Initialize with `init`.
622pub fn LazySegtree (
723 comptime S : type ,
824 comptime op : fn (S , S ) S ,
@@ -15,13 +31,28 @@ pub fn LazySegtree(
1531 return struct {
1632 const Self = @This ();
1733
34+ /// original array length
1835 n : usize ,
36+ /// internal tree size (power of two ≥ n)
1937 size : usize ,
38+ /// tree height
2039 log : usize ,
40+ /// node values
2141 d : []S ,
42+ /// lazy tags
2243 lz : []F ,
2344 allocator : Allocator ,
2445
46+ /// Creates an empty tree of length `n`, initialised with the identity.
47+ /// Deinitialize with `deinit`.
48+ ///
49+ /// # Constraints
50+ ///
51+ /// - $0 \leq n < 10^8$
52+ ///
53+ /// # Complexity
54+ ///
55+ /// - $O(n)$
2556 pub fn init (allocator : Allocator , n : usize ) ! Self {
2657 const size = try math .ceilPowerOfTwo (usize , n );
2758 const log = @ctz (size );
@@ -37,6 +68,17 @@ pub fn LazySegtree(
3768 @memset (self .lz , id ());
3869 return self ;
3970 }
71+
72+ /// Build a tree from an existing slice.
73+ /// Deinitialize with `deinit`.
74+ ///
75+ /// # Constraints
76+ ///
77+ /// - $0 \leq `v.len` < 10^8$
78+ ///
79+ /// # Complexity
80+ ///
81+ /// - $O(n)$ (where $n$ is the length of `v`)
4082 pub fn initFromSlice (allocator : Allocator , v : []const S ) ! Self {
4183 const n = v .len ;
4284 const size = try math .ceilPowerOfTwo (usize , n );
@@ -60,10 +102,26 @@ pub fn LazySegtree(
60102 }
61103 return self ;
62104 }
105+
106+ /// Release all allocated memory.
63107 pub fn deinit (self : * Self ) void {
64108 self .allocator .free (self .d );
65109 self .allocator .free (self .lz );
66110 }
111+
112+ /// Assigns `x` to `a[pos]`
113+ ///
114+ /// # Constraints
115+ ///
116+ /// - $0 \leq p < n$
117+ ///
118+ /// # Panics
119+ ///
120+ /// Panics if the above constraints are not satisfied.
121+ ///
122+ /// # Complexity
123+ ///
124+ /// - $O(\log n)$
67125 pub fn set (self : * Self , pos : usize , x : S ) void {
68126 assert (pos < self .n );
69127 const p = pos + self .size ;
@@ -77,6 +135,20 @@ pub fn LazySegtree(
77135 self .update (p >> i );
78136 }
79137 }
138+
139+ /// Returns `a[p]`
140+ ///
141+ /// # Constraints
142+ ///
143+ /// - $0 \leq p < n$
144+ ///
145+ /// # Panics
146+ ///
147+ /// Panics if the above constraints are not satisfied.
148+ ///
149+ /// # Complexity
150+ ///
151+ /// - $O(\log n)$
80152 pub fn get (self : * Self , pos : usize ) S {
81153 assert (pos < self .n );
82154 const p = pos + self .size ;
@@ -86,9 +158,25 @@ pub fn LazySegtree(
86158 }
87159 return self .d [p ];
88160 }
161+
89162 // pub fn getSlice(self: *Self) []S {
90163 // _ = self;
91164 // }
165+
166+ /// Returns op(a[l], ..., a[r - 1]), assuming the properties of the monoid.
167+ /// Returns e() if l = r.
168+ ///
169+ /// # Constraints
170+ ///
171+ /// - $0 \leq l \leq r \leq n$
172+ ///
173+ /// # Panics
174+ ///
175+ /// Panics if the above constraints are not satisfied.
176+ ///
177+ /// # Complexity
178+ ///
179+ /// - $O(\log n)$
92180 pub fn prod (self : * Self , left : usize , right : usize ) S {
93181 assert (left <= right and right <= self .n );
94182 if (left == right ) {
@@ -125,9 +213,30 @@ pub fn LazySegtree(
125213
126214 return op (sml , smr );
127215 }
216+
217+ /// Returns op(a[0], ..., a[n - 1]), assuming the properties of the monoid.
218+ /// Returns e() if n = 0.
219+ ///
220+ /// # Complexity
221+ ///
222+ /// - $O(1)$
128223 pub fn allProd (self : Self ) S {
129224 return self .d [1 ];
130225 }
226+
227+ /// Applies `a[pos] = f(a[p])`.
228+ ///
229+ /// # Constraints
230+ ///
231+ /// - $0 \leq p < n$
232+ ///
233+ /// # Panics
234+ ///
235+ /// Panics if the above constraints are not satisfied.
236+ ///
237+ /// # Complexity
238+ ///
239+ /// - $O(\log n)$
131240 pub fn apply (self : * Self , pos : usize , f : F ) void {
132241 assert (pos < self .n );
133242 const p = pos + self .size ;
@@ -141,6 +250,20 @@ pub fn LazySegtree(
141250 self .update (p >> i );
142251 }
143252 }
253+
254+ /// Applies `a[i] = f(a[i])` for all `i = l..r-1`.
255+ ///
256+ /// # Constraints
257+ ///
258+ /// - $0 \leq l \leq r \leq n$
259+ ///
260+ /// # Panics
261+ ///
262+ /// Panics if the above constraints are not satisfied.
263+ ///
264+ /// # Complexity
265+ ///
266+ /// - $O(\log n)$
144267 pub fn applyRange (self : * Self , left : usize , right : usize , f : F ) void {
145268 assert (left <= right and right <= self .n );
146269 if (left == right ) {
@@ -190,6 +313,28 @@ pub fn LazySegtree(
190313 }
191314 }
192315 }
316+
317+ /// Applies binary search on the segment tree.
318+ /// Returns an index `r` that satisfies both of the following
319+ ///
320+ /// - `r = l` or `g(context, op(a[l], a[l + 1], ..., a[r - 1])) = true`
321+ /// - `r = n` or `g(context, op(a[l], a[l + 1], ..., a[r])) = false`
322+ ///
323+ /// If `g` is monotone, this is the maximum `r` that satisfies `g(context, op(a[l], a[l + 1], ..., a[r - 1])) = true`.
324+ ///
325+ /// # Constraints
326+ ///
327+ /// - if `g` is called with the same argument, it returns the same value, i.e., `g` has no side effect.
328+ /// - `g(context, e()) = true`
329+ /// - $0 \leq l \leq n$
330+ ///
331+ /// # Panics
332+ ///
333+ /// Panics if the above constraints are not satisfied.
334+ ///
335+ /// # Complexity
336+ ///
337+ /// - $O(\log n)$
193338 pub fn maxRight (self : * Self , left : usize , context : anytype , comptime g : fn (@TypeOf (context ), S ) bool ) usize {
194339 assert (left <= self .n );
195340 assert (g (context , e ()));
@@ -228,6 +373,28 @@ pub fn LazySegtree(
228373 }
229374 return self .n ;
230375 }
376+
377+ /// Applies binary search on the segment tree.
378+ /// Returns an index `l` that satisfies both of the following.
379+ ///
380+ /// - `l = r` or `g(context, op(a[l], a[l + 1], ..., a[r - 1])) = true`
381+ /// - `l = 0` or `g(context, op(a[l - 1], a[l], ..., a[r - 1])) = false`
382+ ///
383+ /// If `g` is monotone, this is the minimum `l` that satisfies `g(context, op(a[l], a[l + 1], ..., a[r - 1])) = true`.
384+ ///
385+ /// # Constraints
386+ ///
387+ /// - if `g` is called with the same argument, it returns the same value, i.e., `g` has no side effect.
388+ /// - `g(context, e()) = true`
389+ /// - $0 \leq r \leq n$
390+ ///
391+ /// # Panics
392+ ///
393+ /// Panics if the above constraints are not satisfied.
394+ ///
395+ /// # Complexity
396+ ///
397+ /// - $O(\log n)$
231398 pub fn minLeft (self : * Self , right : usize , context : anytype , comptime g : fn (@TypeOf (context ), S ) bool ) usize {
232399 assert (right <= self .n );
233400 assert (g (context , e ()));
@@ -284,6 +451,9 @@ pub fn LazySegtree(
284451 };
285452}
286453
454+ /// Sugar helper that turns a *namespace* with fields `S`, `op`, `e`, `F`, `mapping`, `composition`, and `id`.
455+ ///
456+ /// Initialize with `init`.
287457pub fn LazySegtreeFromNS (comptime ns : anytype ) type {
288458 return LazySegtree (
289459 ns .S ,
0 commit comments