use super::ArqSpec;
pub struct DynamicArqNode<T: ArqSpec> {
val: T::S,
app: Option<T::F>,
down: (usize, usize),
}
impl<T: ArqSpec> Clone for DynamicArqNode<T> {
fn clone(&self) -> Self {
Self {
val: self.val.clone(),
app: self.app.clone(),
down: self.down,
}
}
}
impl<T: ArqSpec> Default for DynamicArqNode<T> {
fn default() -> Self {
Self {
val: T::identity(),
app: None,
down: (usize::max_value(), usize::max_value()),
}
}
}
impl<T: ArqSpec> DynamicArqNode<T> {
fn apply(&mut self, f: &T::F, size: i64) {
self.val = T::apply(f, &self.val, size);
if size > 1 {
let h = match self.app {
Some(ref g) => T::compose(f, g),
None => f.clone(),
};
self.app = Some(h);
}
}
}
pub type ArqView = (usize, i64);
pub struct DynamicArq<T: ArqSpec> {
nodes: Vec<DynamicArqNode<T>>,
is_persistent: bool,
}
impl<T: ArqSpec> DynamicArq<T> {
pub fn new(is_persistent: bool) -> Self {
Self {
nodes: vec![],
is_persistent,
}
}
pub fn build_from_identity(&mut self, size: i64) -> ArqView {
self.nodes.push(DynamicArqNode::default());
(self.nodes.len() - 1, size)
}
pub fn build_from_slice(&mut self, init_val: &[T::S]) -> ArqView {
if init_val.len() == 1 {
let root = DynamicArqNode {
val: init_val[0].clone(),
..Default::default()
};
self.nodes.push(root);
(self.nodes.len() - 1, 1)
} else {
let ls = init_val.len() / 2;
let (l_init, r_init) = init_val.split_at(ls);
let l_view = self.build_from_slice(l_init);
let r_view = self.build_from_slice(r_init);
self.merge_equal_sized(l_view, r_view)
}
}
pub fn merge_equal_sized(&mut self, (lp, ls): ArqView, (rp, rs): ArqView) -> ArqView {
assert!(ls == rs || ls + 1 == rs);
let p = self.nodes.len();
let root = DynamicArqNode {
down: (lp, rp),
..Default::default()
};
self.nodes.push(root);
self.pull(p);
(p, ls + rs)
}
pub fn push(&mut self, (p, s): ArqView) -> (ArqView, ArqView) {
if self.nodes[p].down.0 == usize::max_value() {
self.nodes.push(DynamicArqNode::default());
self.nodes.push(DynamicArqNode::default());
self.nodes[p].down = (self.nodes.len() - 2, self.nodes.len() - 1)
};
let (lp, rp) = self.nodes[p].down;
let ls = s / 2;
if let Some(ref f) = self.nodes[p].app.take() {
self.nodes[lp].apply(f, ls);
self.nodes[rp].apply(f, s - ls);
}
((lp, ls), (rp, s - ls))
}
pub fn pull(&mut self, p: usize) {
let (lp, rp) = self.nodes[p].down;
let left_val = &self.nodes[lp].val;
let right_val = &self.nodes[rp].val;
self.nodes[p].val = T::op(left_val, right_val);
}
fn clone_node(&mut self, p_orig: usize) -> usize {
if self.is_persistent {
let node = self.nodes[p_orig].clone();
self.nodes.push(node);
self.nodes.len() - 1
} else {
p_orig
}
}
pub fn update(&mut self, view: ArqView, l: i64, r: i64, f: &T::F) -> ArqView {
let (p_orig, s) = view;
if r < 0 || s - 1 < l {
view
} else if l <= 0 && s - 1 <= r {
let p_clone = self.clone_node(p_orig);
self.nodes[p_clone].apply(f, s);
(p_clone, s)
} else {
let (l_view, r_view) = self.push(view);
let ls = l_view.1;
let p_clone = self.clone_node(p_orig);
let lp_clone = self.update(l_view, l, r, f).0;
let rp_clone = self.update(r_view, l - ls, r - ls, f).0;
self.nodes[p_clone].down = (lp_clone, rp_clone);
self.pull(p_clone);
(p_clone, s)
}
}
pub fn query(&mut self, view: ArqView, l: i64, r: i64) -> T::S {
let (p, s) = view;
if r < 0 || s - 1 < l {
T::identity()
} else if l <= 0 && s - 1 <= r {
self.nodes[p].val.clone()
} else {
let (l_view, r_view) = self.push(view);
let ls = l_view.1;
let l_agg = self.query(l_view, l, r);
let r_agg = self.query(r_view, l - ls, r - ls);
T::op(&l_agg, &r_agg)
}
}
}
pub fn first_negative(arq: &mut DynamicArq<super::specs::AssignMin>, view: ArqView) -> Option<i64> {
let (p, s) = view;
if s == 1 {
Some(0).filter(|_| arq.nodes[p].val < 0)
} else {
let (l_view, r_view) = arq.push(view);
let (lp, ls) = l_view;
if arq.nodes[lp].val < 0 {
first_negative(arq, l_view)
} else {
first_negative(arq, r_view).map(|x| ls + x)
}
}
}