use std::ops::{AddAssign, Bound, RangeBounds, SubAssign};
use crate::errors::{AddError, SumError};
pub struct FenwickTree<I>
where
I: Default + Copy + AddAssign + SubAssign,
{
tree: Vec<I>,
}
impl<I> FenwickTree<I>
where
I: Default + Copy + AddAssign + SubAssign,
{
pub fn with_len(len: usize) -> Self {
Self {
tree: vec![I::default(); len],
}
}
pub fn len(&self) -> usize {
self.tree.len()
}
pub fn sum(&self, bounds: impl RangeBounds<usize>) -> Result<I, SumError> {
let len = self.len();
let mut sum = I::default();
let mut start = start(bounds.start_bound());
let mut end = end(bounds.end_bound(), len);
if start >= len || end > len {
return Err(SumError::OutOfRange {
bounds: as_pair(bounds),
len,
});
}
while end > start {
sum += self.tree[end - 1];
end = prev(end);
}
while start > end {
sum -= self.tree[start - 1];
start = prev(start);
}
return Ok(sum);
fn start(bound: Bound<&usize>) -> usize {
match bound {
Bound::Excluded(&usize::MAX) => usize::MAX,
Bound::Excluded(x) => *x + 1,
Bound::Included(x) => *x,
Bound::Unbounded => 0,
}
}
fn end(bound: Bound<&usize>, len: usize) -> usize {
match bound {
Bound::Included(&usize::MAX) => usize::MAX,
Bound::Included(x) => *x + 1,
Bound::Excluded(x) => *x,
Bound::Unbounded => len,
}
}
fn as_pair(bounds: impl RangeBounds<usize>) -> (Bound<usize>, Bound<usize>) {
let start = cloned(bounds.start_bound());
let end = cloned(bounds.end_bound());
return (start, end);
fn cloned(x: Bound<&usize>) -> Bound<usize> {
match x {
Bound::Unbounded => Bound::Unbounded,
Bound::Included(x) => Bound::Included(*x),
Bound::Excluded(x) => Bound::Excluded(*x),
}
}
}
}
pub fn add(&mut self, mut i: usize, delta: I) -> Result<(), AddError> {
let size = self.len();
if i >= size {
return Err(AddError::IndexOutOfRange { index: i, size });
}
while i < size {
self.tree[i] += delta;
i = next(i);
}
Ok(())
}
}
const fn prev(i: usize) -> usize {
i & (i - 1)
}
const fn next(i: usize) -> usize {
i | (i + 1)
}