haar_lib/algo/
sqrt_decomp.rs1use std::ops::Range;
7
8pub struct SqrtDecomposition {
10 size: usize,
11 block_size: usize,
12 block_num: usize,
13}
14
15impl SqrtDecomposition {
16 pub fn new(size: usize) -> Self {
18 let block_size = size.isqrt();
19 let block_num = size.div_ceil(block_size);
20
21 Self {
22 size,
23 block_size,
24 block_num,
25 }
26 }
27
28 pub fn init(&self, mut init: impl FnMut(usize, Range<usize>)) {
30 for i in 0..self.block_num {
31 let l = i * self.block_size;
32 let r = self.size.min((i + 1) * self.block_size);
33 init(i, l..r);
34 }
35 }
36
37 pub fn block_num(&self) -> usize {
39 self.block_num
40 }
41
42 pub fn query<F>(&self, range: Range<usize>, mut f: F)
46 where
47 F: FnMut(usize, Range<usize>, Option<Range<usize>>),
48 {
49 let Range { start: l, end: r } = range;
50
51 for i in 0..self.block_num {
52 let b_l = i * self.block_size;
53 let b_r = self.size.min((i + 1) * self.block_size);
54
55 if l <= b_l && b_r <= r {
56 f(i, b_l..b_r, None);
57 } else if (b_l <= l && l < b_r) || (b_l < r && r <= b_r) {
58 f(i, b_l..b_r, Some(l.max(b_l)..r.min(b_r)));
59 }
60 }
61 }
62}