Skip to content

Commit f98b627

Browse files
committed
docs: add doc comment for segtree
1 parent 8e14a83 commit f98b627

File tree

1 file changed

+144
-0
lines changed

1 file changed

+144
-0
lines changed

src/segtree.zig

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,41 @@ const math = std.math;
33
const Allocator = std.mem.Allocator;
44
const assert = std.debug.assert;
55

6+
/// Segment Tree
7+
/// Reference: https://en.wikipedia.org/wiki/Segment_tree
8+
///
9+
/// This is a wrapper around a tree of element type T, update operation op, and identity e.
10+
/// The following should be defined.
11+
///
12+
/// - The type `S` of the monoid
13+
/// - The binary operation `op: fn (S, S) S`
14+
/// - The identity element `e: fn () S`
15+
///
16+
/// Initialize with `init`.
617
pub fn Segtree(comptime S: type, comptime op: fn (S, S) S, comptime e: fn () S) type {
718
return struct {
819
const Self = @This();
920

21+
/// original array length
1022
n: usize,
23+
/// internal tree size (power of two ≥ n)
1124
size: usize,
25+
/// tree height used by `set`
1226
log: usize,
27+
/// backing array: [size...2*size)
1328
d: []S,
1429
allocator: Allocator,
1530

31+
/// Creates an empty tree of length `n`, initialised with the identity.
32+
/// Deinitialize with `deinit`.
33+
///
34+
/// # Constraints
35+
///
36+
/// - $0 \leq n < 10^8$
37+
///
38+
/// # Complexity
39+
///
40+
/// - $O(n)$
1641
pub fn init(allocator: Allocator, n: usize) !Self {
1742
const size = try math.ceilPowerOfTwo(usize, n);
1843
const log = @ctz(size);
@@ -26,6 +51,17 @@ pub fn Segtree(comptime S: type, comptime op: fn (S, S) S, comptime e: fn () S)
2651
@memset(self.d, e());
2752
return self;
2853
}
54+
55+
/// Build a tree from an existing slice.
56+
/// Deinitialize with `deinit`.
57+
///
58+
/// # Constraints
59+
///
60+
/// - $0 \leq `v.len` < 10^8$
61+
///
62+
/// # Complexity
63+
///
64+
/// - $O(n)$ (where $n$ is the length of `v`)
2965
pub fn initFromSlice(allocator: Allocator, v: []const S) !Self {
3066
const n = v.len;
3167
const size = try math.ceilPowerOfTwo(usize, n);
@@ -47,9 +83,25 @@ pub fn Segtree(comptime S: type, comptime op: fn (S, S) S, comptime e: fn () S)
4783
}
4884
return self;
4985
}
86+
87+
/// Release all allocated memory.
5088
pub fn deinit(self: *Self) void {
5189
self.allocator.free(self.d);
5290
}
91+
92+
/// Assigns `x` to `a[pos]`
93+
///
94+
/// # Constraints
95+
///
96+
/// - $0 \leq p < n$
97+
///
98+
/// # Panics
99+
///
100+
/// Panics if the above constraints are not satisfied.
101+
///
102+
/// # Complexity
103+
///
104+
/// - $O(\log n)$
53105
pub fn set(self: *Self, pos: usize, x: S) void {
54106
assert(pos < self.n);
55107
const p = pos + self.size;
@@ -58,13 +110,48 @@ pub fn Segtree(comptime S: type, comptime op: fn (S, S) S, comptime e: fn () S)
58110
self.update(p >> @intCast(i));
59111
}
60112
}
113+
114+
/// Returns `a[p]`
115+
///
116+
/// # Constraints
117+
///
118+
/// - $0 \leq p < n$
119+
///
120+
/// # Panics
121+
///
122+
/// Panics if the above constraints are not satisfied.
123+
///
124+
/// # Complexity
125+
///
126+
/// - $O(1)$
61127
pub fn get(self: *Self, p: usize) S {
62128
assert(p < self.n);
63129
return self.d[p + self.size];
64130
}
131+
132+
/// Returns the underlying leaf slice `[0, n)`.
133+
///
134+
/// # Complexity
135+
///
136+
/// - $O(1)$
65137
pub fn getSlice(self: *Self) []S {
66138
return self.d[self.size .. self.size + self.n];
67139
}
140+
141+
/// Returns op(a[l], ..., a[r - 1]), assuming the properties of the monoid.
142+
/// Returns e() if l = r.
143+
///
144+
/// # Constraints
145+
///
146+
/// - $0 \leq l \leq r < n$
147+
///
148+
/// # Panics
149+
///
150+
/// Panics if the above constraints are not satisfied.
151+
///
152+
/// # Complexity
153+
///
154+
/// - $O(\log n)$
68155
pub fn prod(self: *Self, left: usize, right: usize) S {
69156
assert(left <= right and right <= self.n);
70157

@@ -90,9 +177,38 @@ pub fn Segtree(comptime S: type, comptime op: fn (S, S) S, comptime e: fn () S)
90177

91178
return op(sml, smr);
92179
}
180+
181+
/// Returns op(a[0], ..., a[n - 1]), assuming the properties of the monoid.
182+
/// Returns e() if n = 0.
183+
///
184+
/// # Complexity
185+
///
186+
/// - $O(1)$
93187
pub fn allProd(self: *Self) S {
94188
return self.d[1];
95189
}
190+
191+
/// Applies binary search on the segment tree.
192+
/// Returns an index `r` that satisfies both of the following.
193+
///
194+
/// - `r = l` or `f(context, op(a[l], a[l + 1], ..., a[r - 1])) = true`
195+
/// - `r = n` or `f(context, op(a[l], a[l + 1], ..., a[r])) = false`
196+
///
197+
/// If `f` is monotone, this is the maximum `r` that satisfies `f(context, op(a[l], a[l + 1], ..., a[r - 1])) = true`.
198+
///
199+
/// # Constraints
200+
///
201+
/// - if `f` is called with the same argument, it returns the same value, i.e., `f/ has no side effect.
202+
/// - `f(context, e()) = true`
203+
/// - $0 \leq l \leq n$
204+
///
205+
/// # Panics
206+
///
207+
/// Panics if the above constraints are not satisfied.
208+
///
209+
/// # Complexity
210+
///
211+
/// - $O(\log n)$
96212
pub fn maxRight(self: *Self, left: usize, context: anytype, comptime f: fn (@TypeOf(context), S) bool) usize {
97213
assert(left <= self.n);
98214
assert(f(context, e()));
@@ -126,6 +242,28 @@ pub fn Segtree(comptime S: type, comptime op: fn (S, S) S, comptime e: fn () S)
126242
}
127243
return self.n;
128244
}
245+
246+
/// Applies binary search on the segment tree.
247+
/// Returns an index `l` that satisfies both of the following.
248+
///
249+
/// - `l = r` or `f(context, op(a[l], a[l + 1], ..., a[r - 1])) = true`
250+
/// - `l = 0` or `f(context, op(a[l - 1], a[l], ..., a[r - 1])) = false`
251+
///
252+
/// If `f` is monotone, this is the minimum `l` that satisfies `f(context, op(a[l], a[l + 1], ..., a[r - 1])) = true`.
253+
///
254+
/// # Constraints
255+
///
256+
/// - if `f` is called with the same argument, it returns the same value, i.e., `f` has no side effect.
257+
/// - `f(context, e()) = true`
258+
/// - $0 \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)$
129267
pub fn minLeft(self: *Self, right: usize, context: anytype, comptime f: fn (@TypeOf(context), S) bool) usize {
130268
assert(right <= self.n);
131269
assert(f(context, e()));
@@ -159,12 +297,18 @@ pub fn Segtree(comptime S: type, comptime op: fn (S, S) S, comptime e: fn () S)
159297
}
160298
return 0;
161299
}
300+
301+
/// Internal helper function:
302+
/// Recomputes node `k` from its two children.
162303
fn update(self: *Self, k: usize) void {
163304
self.d[k] = op(self.d[2 * k], self.d[2 * k + 1]);
164305
}
165306
};
166307
}
167308

309+
/// Sugar helper that turns a *namespace* with fields `S`, `op`, and `e`.
310+
///
311+
/// Initialize with `init`.
168312
pub fn SegtreeFromNS(comptime ns: anytype) type {
169313
return Segtree(
170314
ns.S,

0 commit comments

Comments
 (0)