use super::ArqSpec;
pub struct StaticArq<T: ArqSpec> {
val: Vec<T::S>,
app: Vec<Option<T::F>>,
}
impl<T: ArqSpec> StaticArq<T> {
pub fn new(init_val: &[T::S]) -> Self {
let size = init_val.len();
let mut val = vec![T::identity(); size];
val.extend_from_slice(init_val);
let app = vec![None; size];
let mut arq = Self { val, app };
for p in (0..size).rev() {
arq.pull(p);
}
arq
}
fn apply(&mut self, p: usize, f: &T::F, s: i64) {
self.val[p] = T::apply(f, &self.val[p], s);
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() {
let s = ((self.app.len() + p - 1) / p / 2).next_power_of_two() as i64;
self.apply(p << 1, f, s);
self.apply(p << 1 | 1, f, s);
}
}
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) {
let one_plus_floor_log_p = (p + 1).next_power_of_two().trailing_zeros();
for i in (1..one_plus_floor_log_p).rev() {
self.push(p >> i);
}
}
fn pull_from(&mut self, mut p: usize) {
while p > 1 {
p >>= 1;
self.pull(p);
}
}
pub fn update(&mut self, mut l: usize, mut r: usize, f: &T::F) {
l += self.app.len();
r += self.app.len();
if l < r {
self.push_to(l);
}
self.push_to(r);
let (mut l0, mut r0, mut s) = (1, 1, 1);
while l <= r {
if l & 1 == 1 {
self.apply(l, f, s);
l0 = l0.max(l);
l += 1;
}
if r & 1 == 0 {
self.apply(r, f, s);
r0 = r0.max(r);
r -= 1;
}
l >>= 1;
r >>= 1;
s <<= 1;
}
self.pull_from(l0);
self.pull_from(r0);
}
pub fn query(&mut self, mut l: usize, mut r: usize) -> T::S {
l += self.app.len();
r += self.app.len();
if l < r {
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 fn first_negative(arq: &mut StaticArq<super::specs::AssignMin>) -> Option<usize> {
assert!(arq.app.len().is_power_of_two());
let mut p = 1;
if arq.val[p] >= 0 {
None
} else {
while p < arq.app.len() {
arq.push(p);
p <<= 1;
if arq.val[p] >= 0 {
p |= 1;
}
}
Some(p - arq.app.len())
}
}