1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
pub mod sparse_table {

    pub struct SparseTable<T, F> {
        data: Vec<Vec<T>>,
        op: F,
    }

    impl<T, F> SparseTable<T, F>
    where
        T: Copy,
        F: Fn(T, T) -> T,
    {
        pub fn from(v: &[T], init: T, op: F) -> Self {
            let size = v.len().next_power_of_two();
            let count = size.trailing_zeros() as usize + 1;
            let mut data = vec![vec![init; size]; count];
            for (i, v) in v.iter().cloned().enumerate() {
                data[0][i] = v;
            }
            for c in 1..count {
                for i in 0..size {
                    let next = std::cmp::min(size - 1, i + (1 << (c - 1)));
                    data[c][i] = op(data[c - 1][i], data[c - 1][next]);
                }
            }

            Self { data, op }
        }

        /// get the result for [l, r)
        pub fn get(&self, l: usize, r: usize) -> T {
            assert!(l < r);
            let length = r - l;
            if length == 1 {
                return self.data[0][l];
            }
            let block_size = length.next_power_of_two() >> 1;
            let c = block_size.trailing_zeros() as usize;
            let left = self.data[c][l];
            let right = self.data[c][r - block_size];
            (self.op)(left, right)
        }
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use rand::{thread_rng, Rng};
    use std::cmp;

    #[test]
    fn test_small() {
        let v = vec![1, 9, 9, 1, 0, 7, 1, 7];
        let sparse_table = sparse_table::SparseTable::from(&v, 0, |a, b| cmp::min(a, b));
        for l in 0..8 {
            for r in (l + 1)..9 {
                let &min = v[l..r].iter().min().unwrap();
                assert_eq!(sparse_table.get(l, r), min);
            }
        }
    }

    #[test]
    fn test_sparse_table_with_random_array() {
        let n = 1000;
        let v: Vec<u64> = (0..n)
            .map(|_| thread_rng().gen_range(0, 1000000000))
            .collect();
        let sparse_table = sparse_table::SparseTable::from(&v, 0, cmp::min);
        for l in 0..n {
            for r in (l + 1)..(n + 1) {
                let &min = v[l..r].iter().min().unwrap();
                assert_eq!(sparse_table.get(l, r), min);
            }
        }
    }
}