Skip to main content

competitive/data_structure/
accumulate.rs

1use super::{AbelianGroup, AbelianMonoid, Group, Monoid, RangeBoundsExt};
2use std::{
3    fmt::{self, Debug, Formatter},
4    iter::FromIterator,
5    ops::RangeBounds,
6};
7
8/// Accumlated data
9pub struct Accumulate<M>
10where
11    M: Monoid,
12{
13    data: Vec<M::T>,
14}
15
16impl<M> Debug for Accumulate<M>
17where
18    M: Monoid<T: Debug>,
19{
20    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
21        f.debug_struct("Accumulate")
22            .field("data", &self.data)
23            .finish()
24    }
25}
26
27impl<M> FromIterator<M::T> for Accumulate<M>
28where
29    M: Monoid,
30{
31    fn from_iter<T>(iter: T) -> Self
32    where
33        T: IntoIterator<Item = M::T>,
34    {
35        let iter = iter.into_iter();
36        let (lower, _) = iter.size_hint();
37        let mut data = Vec::with_capacity(lower.saturating_add(1));
38        let mut acc = M::unit();
39        for x in iter {
40            let y = M::operate(&acc, &x);
41            data.push(acc);
42            acc = y;
43        }
44        data.push(acc);
45        Self { data }
46    }
47}
48
49impl<M> Accumulate<M>
50where
51    M: Monoid,
52{
53    pub fn from_vec(mut data: Vec<M::T>) -> Self {
54        let mut acc = M::unit();
55        for x in &mut data {
56            let y = M::operate(&acc, x);
57            *x = acc;
58            acc = y;
59        }
60        data.push(acc);
61        Self { data }
62    }
63
64    /// Return fold of \[0, k\)
65    pub fn accumulate(&self, k: usize) -> M::T {
66        assert!(
67            k < self.data.len(),
68            "index out of range: the len is {} but the index is {}",
69            self.data.len(),
70            k
71        );
72        unsafe { self.data.get_unchecked(k) }.clone()
73    }
74}
75
76impl<M> Accumulate<M>
77where
78    M: Group,
79{
80    /// Return fold of range
81    pub fn fold<R>(&self, range: R) -> M::T
82    where
83        R: RangeBounds<usize>,
84    {
85        let n = self.data.len() - 1;
86        let range = range.to_range_bounded(0, n).expect("invalid range");
87        let (l, r) = (range.start, range.end);
88        assert!(l <= r, "bad range [{}, {})", l, r);
89        M::operate(&M::inverse(unsafe { self.data.get_unchecked(l) }), unsafe {
90            self.data.get_unchecked(r)
91        })
92    }
93}
94
95/// 2-dimensional accumlated data
96pub struct Accumulate2d<M>
97where
98    M: AbelianMonoid,
99{
100    h: usize,
101    w: usize,
102    data: Vec<M::T>,
103}
104
105impl<M> Debug for Accumulate2d<M>
106where
107    M: AbelianMonoid<T: Debug>,
108{
109    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
110        f.debug_struct("Accumulate2d")
111            .field("h", &self.h)
112            .field("w", &self.w)
113            .field("data", &self.data)
114            .finish()
115    }
116}
117
118impl<M> Accumulate2d<M>
119where
120    M: AbelianMonoid,
121{
122    pub fn new(arr2d: &[Vec<M::T>]) -> Self {
123        let h = arr2d.len();
124        assert!(h > 0);
125        let w = arr2d[0].len();
126        assert!(w > 0);
127        let w1 = w + 1;
128        let mut data = Vec::with_capacity((h + 1) * w1);
129        data.resize_with(w1, M::unit);
130        for (i, arr) in arr2d.iter().enumerate() {
131            assert_eq!(w, arr.len(), "expected 2d array");
132            let mut acc = M::unit();
133            for (j, x) in arr.iter().enumerate() {
134                let y = M::operate(&acc, x);
135                data.push(M::operate(&acc, unsafe { data.get_unchecked(w1 * i + j) }));
136                acc = y;
137            }
138            data.push(M::operate(&acc, unsafe { data.get_unchecked(w1 * i + w) }));
139        }
140        Self { h, w, data }
141    }
142    pub fn from_fn<F>(h: usize, w: usize, mut f: F) -> Self
143    where
144        F: FnMut(usize, usize) -> M::T,
145    {
146        let w1 = w + 1;
147        let mut data = Vec::with_capacity((h + 1) * w1);
148        data.resize_with(w1, M::unit);
149        for i in 0..h {
150            let mut acc = M::unit();
151            for j in 0..w {
152                let y = M::operate(&acc, &f(i, j));
153                data.push(M::operate(&acc, unsafe { data.get_unchecked(w1 * i + j) }));
154                acc = y;
155            }
156            data.push(M::operate(&acc, unsafe { data.get_unchecked(w1 * i + w) }));
157        }
158        Self { h, w, data }
159    }
160    /// Return fold of \[0, x\) × \[0, y\)
161    pub fn accumulate(&self, x: usize, y: usize) -> M::T {
162        let h1 = self.h + 1;
163        let w1 = self.w + 1;
164        assert!(
165            x < h1,
166            "index out of range: the first len is {} but the index is {}",
167            h1,
168            x
169        );
170        assert!(
171            y < w1,
172            "index out of range: the second len is {} but the index is {}",
173            w1,
174            y
175        );
176        unsafe { self.data.get_unchecked(w1 * x + y) }.clone()
177    }
178}
179
180impl<M> Accumulate2d<M>
181where
182    M: AbelianGroup,
183{
184    /// Return fold of range
185    pub fn fold<R0, R1>(&self, range0: R0, range1: R1) -> M::T
186    where
187        R0: RangeBounds<usize>,
188        R1: RangeBounds<usize>,
189    {
190        let range0 = range0.to_range_bounded(0, self.h).expect("invalid range");
191        let range1 = range1.to_range_bounded(0, self.w).expect("invalid range");
192        let (xl, xr) = (range0.start, range0.end);
193        let (yl, yr) = (range1.start, range1.end);
194        assert!(xl <= xr, "bad range [{}, {})", xl, xr);
195        assert!(yl <= yr, "bad range [{}, {})", yl, yr);
196        let w1 = self.w + 1;
197        unsafe {
198            M::rinv_operate(
199                &M::operate(
200                    self.data.get_unchecked(w1 * xl + yl),
201                    self.data.get_unchecked(w1 * xr + yr),
202                ),
203                &M::operate(
204                    self.data.get_unchecked(w1 * xl + yr),
205                    self.data.get_unchecked(w1 * xr + yl),
206                ),
207            )
208        }
209    }
210}
211
212pub struct AccumulateKd<const K: usize, M>
213where
214    M: AbelianMonoid,
215{
216    dim: [usize; K],
217    offset: [usize; K],
218    data: Vec<M::T>,
219}
220
221impl<const K: usize, M> Debug for AccumulateKd<K, M>
222where
223    M: AbelianMonoid<T: Debug>,
224{
225    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
226        f.debug_struct("AccumulateKd")
227            .field("dim", &self.dim)
228            .field("offset", &self.offset)
229            .field("data", &self.data)
230            .finish()
231    }
232}
233
234impl<const K: usize, M> AccumulateKd<K, M>
235where
236    M: AbelianMonoid,
237{
238    pub fn from_fn(dim: [usize; K], mut f: impl FnMut([usize; K]) -> M::T) -> Self {
239        fn fill<const K: usize, T>(
240            dim: &[usize; K],
241            offset: &[usize; K],
242            data: &mut [T],
243            f: &mut impl FnMut([usize; K]) -> T,
244            mut index: [usize; K],
245            pos: usize,
246        ) {
247            if pos < K {
248                for i in 0..dim[pos] {
249                    index[pos] = i;
250                    fill(dim, offset, data, f, index, pos + 1);
251                }
252            } else {
253                let i: usize = index.iter().zip(offset).map(|(x, y)| (x + 1) * y).sum();
254                data[i] = f(index);
255            }
256        }
257
258        let mut offset = [1; K];
259        for d in (1..K).rev() {
260            offset[d - 1] = offset[d] * (dim[d] + 1);
261        }
262        let size = offset[0] * (dim[0] + 1);
263        let mut data = vec![M::unit(); size];
264        fill(&dim, &offset, &mut data, &mut f, [0; K], 0);
265        for d in 0..K {
266            for i in 1..size {
267                if i / offset[d] % (dim[d] + 1) != 0 {
268                    data[i] = M::operate(&data[i], &data[i - offset[d]]);
269                }
270            }
271        }
272        Self { dim, offset, data }
273    }
274    pub fn accumulate(&self, x: [usize; K]) -> M::T {
275        for (d, x) in x.into_iter().enumerate() {
276            assert!(
277                x <= self.dim[d],
278                "index out of range: the len is {} but the index is {}",
279                self.dim[d] + 1,
280                x
281            );
282        }
283        let p: usize = x.iter().zip(&self.offset).map(|(x, y)| x * y).sum();
284        unsafe { self.data.get_unchecked(p) }.clone()
285    }
286}
287
288impl<const K: usize, M> AccumulateKd<K, M>
289where
290    M: AbelianGroup,
291{
292    pub fn fold<R>(&self, ranges: [R; K]) -> M::T
293    where
294        R: RangeBounds<usize>,
295    {
296        let ranges: [_; K] = std::array::from_fn(|i| {
297            let range = ranges[i]
298                .to_range_bounded(0, self.dim[i])
299                .expect("invalid range");
300            let (l, r) = (range.start, range.end);
301            assert!(l <= r, "bad range [{}, {})", l, r);
302            [l, r]
303        });
304        let mut p: usize = ranges
305            .iter()
306            .zip(&self.offset)
307            .map(|(range, offset)| range[1] * offset)
308            .sum();
309        let delta: [_; K] = std::array::from_fn(|d| (ranges[d][1] - ranges[d][0]) * self.offset[d]);
310        let mut acc = M::unit();
311        let len = 1usize << K;
312        let mut gray = 0usize;
313        let mut inv = false;
314        for i in 0..len {
315            if inv {
316                acc = M::rinv_operate(&acc, unsafe { self.data.get_unchecked(p) });
317            } else {
318                acc = M::operate(&acc, unsafe { self.data.get_unchecked(p) });
319            }
320            if i + 1 < len {
321                let next_gray = (i + 1) ^ ((i + 1) >> 1);
322                let changed = gray ^ next_gray;
323                let d = changed.trailing_zeros() as usize;
324                if (next_gray >> d) & 1 == 1 {
325                    p -= delta[d];
326                } else {
327                    p += delta[d];
328                }
329                gray = next_gray;
330                inv = !inv;
331            }
332        }
333        acc
334    }
335}
336
337#[cfg(test)]
338mod tests {
339    use super::*;
340    use crate::{
341        algebra::{AdditiveOperation, LinearOperation, Magma, Unital},
342        num::mint_basic::MInt1000000007,
343        rand,
344        tools::Xorshift,
345    };
346    type M = LinearOperation<MInt1000000007>;
347    type A = AdditiveOperation<MInt1000000007>;
348
349    #[test]
350    fn test_accumlate() {
351        let mut rng = Xorshift::default();
352        const Q: usize = 1_000;
353        const N: usize = 50;
354        for n in 0..Q {
355            let n = n % N;
356            rand!(rng, v: [(.., ..); n], t: 0..2);
357            let acc: Accumulate<M> = if t == 0 {
358                v.iter().cloned().collect()
359            } else {
360                Accumulate::from_vec(v.clone())
361            };
362            for r in 0..=n {
363                assert_eq!(
364                    v[..r].iter().fold(M::unit(), |x, y| M::operate(&x, y)),
365                    acc.accumulate(r)
366                );
367                for l in 0..=r {
368                    assert_eq!(
369                        v[l..r].iter().fold(M::unit(), |x, y| M::operate(&x, y)),
370                        acc.fold(l..r)
371                    );
372                }
373            }
374        }
375    }
376
377    #[test]
378    fn test_accumlate2d() {
379        let mut rng = Xorshift::default();
380        const Q: usize = 1_000;
381        const N: usize = 10;
382        for i in 0..Q {
383            let h = i % N + 1;
384            let w = i / N % N + 1;
385            rand!(rng, v: [[..; w]; h]);
386            let acc2d = Accumulate2d::<A>::new(&v);
387            for xr in 0..=h {
388                for yr in 0..=w {
389                    assert_eq!(
390                        v[..xr]
391                            .iter()
392                            .flat_map(|v| v[..yr].iter())
393                            .fold(A::unit(), |x, y| A::operate(&x, y)),
394                        acc2d.accumulate(xr, yr)
395                    );
396                    for xl in 0..=xr {
397                        for yl in 0..=yr {
398                            assert_eq!(
399                                v[xl..xr]
400                                    .iter()
401                                    .flat_map(|v| v[yl..yr].iter())
402                                    .fold(A::unit(), |x, y| A::operate(&x, y)),
403                                acc2d.fold(xl..xr, yl..yr)
404                            );
405                        }
406                    }
407                }
408            }
409        }
410    }
411
412    #[test]
413    fn test_accumlate2d_from_fn() {
414        let mut rng = Xorshift::default();
415        const Q: usize = 1_000;
416        const N: usize = 10;
417        for i in 0..Q {
418            let h = i % N;
419            let w = i / N % N;
420            rand!(rng, v: [[..; w]; h]);
421            let acc2d = Accumulate2d::<A>::from_fn(h, w, |i, j| v[i][j]);
422            for xr in 0..=h {
423                for yr in 0..=w {
424                    assert_eq!(
425                        v[..xr]
426                            .iter()
427                            .flat_map(|v| v[..yr].iter())
428                            .fold(A::unit(), |x, y| A::operate(&x, y)),
429                        acc2d.accumulate(xr, yr)
430                    );
431                    for xl in 0..=xr {
432                        for yl in 0..=yr {
433                            assert_eq!(
434                                v[xl..xr]
435                                    .iter()
436                                    .flat_map(|v| v[yl..yr].iter())
437                                    .fold(A::unit(), |x, y| A::operate(&x, y)),
438                                acc2d.fold(xl..xr, yl..yr)
439                            );
440                        }
441                    }
442                }
443            }
444        }
445    }
446
447    #[test]
448    fn test_accumlatekd_from_fn_3d() {
449        let mut rng = Xorshift::default();
450        const N: usize = 5;
451        for i in 0..N * N * N {
452            let dim = [i % N, i / N % N, i / N / N % N];
453            rand!(rng, v: [[[..; dim[2]]; dim[1]]; dim[0]]);
454            let acc = AccumulateKd::<3, A>::from_fn(dim, |[i, j, k]| v[i][j][k]);
455            for xr in 0..=dim[0] {
456                for yr in 0..=dim[1] {
457                    for zr in 0..=dim[2] {
458                        assert_eq!(
459                            v[..xr]
460                                .iter()
461                                .flat_map(|v| v[..yr].iter().flat_map(|v| v[..zr].iter()))
462                                .fold(A::unit(), |x, y| A::operate(&x, y)),
463                            acc.accumulate([xr, yr, zr])
464                        );
465                        for xl in 0..=xr {
466                            for yl in 0..=yr {
467                                for zl in 0..=zr {
468                                    assert_eq!(
469                                        v[xl..xr]
470                                            .iter()
471                                            .flat_map(|v| v[yl..yr]
472                                                .iter()
473                                                .flat_map(|v| v[zl..zr].iter()))
474                                            .fold(A::unit(), |x, y| A::operate(&x, y)),
475                                        acc.fold([xl..xr, yl..yr, zl..zr])
476                                    );
477                                }
478                            }
479                        }
480                    }
481                }
482            }
483        }
484    }
485
486    #[test]
487    fn test_accumlatekd_from_fn_4d() {
488        let mut rng = Xorshift::default();
489        const N: usize = 4;
490        for i in 0..N * N * N * N {
491            let dim = [i % N, i / N % N, i / N / N % N, i / N / N / N % N];
492            rand!(rng, v: [[[[..; dim[3]]; dim[2]]; dim[1]]; dim[0]]);
493            let acc = AccumulateKd::<4, A>::from_fn(dim, |[i, j, k, l]| v[i][j][k][l]);
494            for xr in 0..=dim[0] {
495                for yr in 0..=dim[1] {
496                    for zr in 0..=dim[2] {
497                        for wr in 0..=dim[3] {
498                            assert_eq!(
499                                v[..xr]
500                                    .iter()
501                                    .flat_map(|v| v[..yr]
502                                        .iter()
503                                        .flat_map(|v| v[..zr].iter().flat_map(|v| v[..wr].iter())))
504                                    .fold(A::unit(), |x, y| A::operate(&x, y)),
505                                acc.accumulate([xr, yr, zr, wr])
506                            );
507                            for xl in 0..=xr {
508                                for yl in 0..=yr {
509                                    for zl in 0..=zr {
510                                        for wl in 0..=wr {
511                                            assert_eq!(
512                                                v[xl..xr]
513                                                    .iter()
514                                                    .flat_map(|v| v[yl..yr]
515                                                        .iter()
516                                                        .flat_map(|v| v[zl..zr]
517                                                            .iter()
518                                                            .flat_map(|v| v[wl..wr].iter())))
519                                                    .fold(A::unit(), |x, y| A::operate(&x, y)),
520                                                acc.fold([xl..xr, yl..yr, zl..zr, wl..wr])
521                                            );
522                                        }
523                                    }
524                                }
525                            }
526                        }
527                    }
528                }
529            }
530        }
531    }
532}