pub struct ArqTree<T: ArqSpec> {
app: Vec<Option<T::F>>,
val: Vec<T::M>,
}
impl<T: ArqSpec> ArqTree<T>
where
T::F: Clone,
{
pub fn new(init_val: Vec<T::M>) -> Self {
let size = init_val.len();
let mut val = (0..size).map(|_| T::identity()).collect::<Vec<_>>();
val.append(&mut { init_val });
let app = vec![None; size];
let mut arq = Self { app, val };
for p in (0..size).rev() {
arq.pull(p);
}
arq
}
fn apply(&mut self, p: usize, f: &T::F) {
self.val[p] = T::apply(f, &self.val[p]);
if let Some(lazy) = self.app.get_mut(p) {
let h = match *lazy {
Some(ref g) => T::compose(f, g),
None => f.clone(),
};
*lazy = Some(h);
}
}
fn push(&mut self, p: usize) {
if let Some(ref f) = self.app[p].take() {
self.apply(p << 1, f);
self.apply(p << 1 | 1, f);
}
}
fn pull(&mut self, p: usize) {
self.val[p] = T::op(&self.val[p << 1], &self.val[p << 1 | 1]);
}
fn push_to(&mut self, p: usize) {
for s in (1..32).rev() {
self.push(p >> s);
}
}
fn pull_from(&mut self, mut p: usize) {
while p > 1 {
p >>= 1;
self.pull(p);
}
}
pub fn modify(&mut self, mut l: usize, mut r: usize, f: &T::F) {
l += self.app.len();
r += self.app.len();
self.push_to(l);
self.push_to(r);
let (mut l0, mut r0) = (1, 1);
while l <= r {
if l & 1 == 1 {
self.apply(l, f);
l0 = l0.max(l);
l += 1;
}
if r & 1 == 0 {
self.apply(r, f);
r0 = r0.max(r);
r -= 1;
}
l >>= 1;
r >>= 1;
}
self.pull_from(l0);
self.pull_from(r0);
}
pub fn query(&mut self, mut l: usize, mut r: usize) -> T::M {
l += self.app.len();
r += self.app.len();
self.push_to(l);
self.push_to(r);
let (mut l_agg, mut r_agg) = (T::identity(), T::identity());
while l <= r {
if l & 1 == 1 {
l_agg = T::op(&l_agg, &self.val[l]);
l += 1;
}
if r & 1 == 0 {
r_agg = T::op(&self.val[r], &r_agg);
r -= 1;
}
l >>= 1;
r >>= 1;
}
T::op(&l_agg, &r_agg)
}
}
pub trait ArqSpec {
type F;
type M;
fn compose(f: &Self::F, g: &Self::F) -> Self::F;
fn apply(f: &Self::F, a: &Self::M) -> Self::M;
fn op(a: &Self::M, b: &Self::M) -> Self::M;
fn identity() -> Self::M;
}
pub struct AssignMin;
impl ArqSpec for AssignMin {
type F = i64;
type M = i64;
fn compose(&f: &Self::F, _: &Self::F) -> Self::F {
f
}
fn apply(&f: &Self::F, _: &Self::M) -> Self::M {
f
}
fn op(&a: &Self::M, &b: &Self::M) -> Self::M {
a.min(b)
}
fn identity() -> Self::M {
Self::M::max_value()
}
}
pub fn first_negative(arq: &mut ArqTree<AssignMin>) -> i32 {
assert!(arq.app.len().is_power_of_two());
let mut i = 1;
if arq.val[i] >= 0 {
return -1;
}
while i < arq.app.len() {
arq.push(i);
i <<= 1;
if arq.val[i] >= 0 {
i |= 1;
}
}
let pos = i - arq.app.len();
pos as i32
}
pub struct AssignSum;
impl ArqSpec for AssignSum {
type F = i64;
type M = (i64, i64);
fn compose(&f: &Self::F, _: &Self::F) -> Self::F {
f
}
fn apply(&f: &Self::F, &(_, s): &Self::M) -> Self::M {
(f * s, s)
}
fn op(&(a, s): &Self::M, &(b, t): &Self::M) -> Self::M {
(a + b, s + t)
}
fn identity() -> Self::M {
(0, 0)
}
}
pub struct SupplyDemand;
impl ArqSpec for SupplyDemand {
type F = (i64, i64);
type M = (i64, i64, i64); fn compose(_: &Self::F, _: &Self::F) -> Self::F {
unimplemented!()
}
fn apply(&(p_add, o_add): &Self::F, &(p, o, _): &Self::M) -> Self::M {
let p = p + p_add;
let o = o + o_add;
(p, o, p.min(o))
}
fn op((p1, o1, s1): &Self::M, (p2, o2, s2): &Self::M) -> Self::M {
let extra = (p1 - s1).min(o2 - s2);
(p1 + p2, o1 + o2, s1 + s2 + extra)
}
fn identity() -> Self::M {
(0, 0, 0)
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_rmq() {
let mut arq = ArqTree::<AssignMin>::new(vec![0; 10]);
assert_eq!(arq.query(0, 9), 0);
arq.modify(2, 4, &-5);
arq.modify(5, 7, &-3);
arq.modify(1, 6, &1);
assert_eq!(arq.query(0, 9), -3);
}
#[test]
fn test_rmq_binary_search() {
let vec = vec![0, 1, -2, 3, -4, -5, 6, -7];
let mut arq = ArqTree::<AssignMin>::new(vec);
let pos = first_negative(&mut arq);
arq.modify(2, 7, &0);
let pos_zeros = first_negative(&mut arq);
assert_eq!(pos, 2);
assert_eq!(pos_zeros, -1);
}
#[test]
fn test_range_sum() {
let mut arq = ArqTree::<AssignSum>::new(vec![(0, 1); 10]);
assert_eq!(arq.query(0, 9), (0, 10));
arq.modify(1, 3, &10);
arq.modify(3, 5, &1);
assert_eq!(arq.query(0, 9), (23, 10));
}
#[test]
fn test_supply_demand() {
let mut arq = ArqTree::<SupplyDemand>::new(vec![(0, 0, 0); 10]);
arq.modify(1, 1, &(25, 100));
arq.modify(3, 3, &(100, 30));
arq.modify(9, 9, &(0, 20));
assert_eq!(arq.query(0, 9), (125, 150, 75));
}
}