dsalgo/
sparse_table_with_static_idempotent_binary_operation.rs1pub trait BinaryOp {
2 type T;
3
4 fn f(
5 _: Self::T,
6 _: Self::T,
7 ) -> Self::T;
8}
9
10pub struct SparseTable<F: BinaryOp>(Vec<Vec<F::T>>);
11
12impl<F: BinaryOp> SparseTable<F>
13where
14 F::T: Clone,
15{
16 pub fn new(a: &[F::T]) -> Self {
17 let n = a.len();
18
19 assert!(n > 0);
20
21 let h = n.next_power_of_two().trailing_zeros().max(1) as usize;
22
23 let mut data = vec![vec![]; h];
24
25 data[0] = a.to_vec();
26
27 for i in 1..h {
28 let d1 = 1 << i;
29
30 let d0 = d1 >> 1;
31
32 let w = n - d1 + 1;
33
34 data[i] = (0..w)
35 .map(|j| {
36 F::f(data[i - 1][j].clone(), data[i - 1][j + d0].clone())
37 })
38 .collect();
39 }
40
41 Self(data)
42 }
43
44 pub fn size(&self) -> usize {
45 self.0[0].len()
46 }
47
48 pub fn get(
49 &self,
50 l: usize,
51 r: usize,
52 ) -> F::T {
53 assert!(l < r && r <= self.size());
54
55 if r - l == 1 {
56 return self.0[0][l].clone();
57 }
58
59 let i = (r - l).next_power_of_two().trailing_zeros() as usize - 1;
60
61 F::f(self.0[i][l].clone(), self.0[i][r - (1 << i)].clone())
62 }
63}
64
65#[cfg(test)]
66
67mod tests {
68
69 use super::*;
70
71 #[test]
72
73 fn test() {
74 struct F;
75
76 impl BinaryOp for F {
77 type T = usize;
78
79 fn f(
80 x: usize,
81 y: usize,
82 ) -> usize {
83 x.min(y)
84 }
85 }
86
87 let a: Vec<usize> = vec![0, 4, 2, 8, 5, 1];
88
89 let sp = SparseTable::<F>::new(&a);
90
91 assert_eq!(sp.get(0, 4), 0);
92
93 assert_eq!(sp.get(3, 4), 8);
94
95 assert_eq!(sp.get(1, 6), 1);
96 }
97}