Segment Tree Range Sum

use std::{ cmp::Ordering, collections::{BinaryHeap, HashMap, HashSet}, fmt::{Binary, Debug}, }; fn main() { let vec = vec![1, 3, 5]; let mut num_array = NumArray::new(vec); println!("{:?}", num_array.sum_range(0, 2)); println!("{:?}", num_array.update(1, 2)); println!("{:?}", num_array.sum_range(0, 2)) } struct SegmentTreeNode<'a, T> { left_node: Option<Box<SegmentTreeNode<'a, T>>>, right_node: Option<Box<SegmentTreeNode<'a, T>>>, left_index: usize, right_index: usize, info: T, operation: &'a dyn Fn(&T, &T) -> T, } impl<'a, T> Debug for SegmentTreeNode<'a, T> where T: Debug, { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("SegmentTreeNode") .field("left_node", &self.left_node) .field("right_node", &self.right_node) .field("left_index", &self.left_index) .field("right_index", &self.right_index) .field("info", &self.info) .finish() } } impl<'a, T> SegmentTreeNode<'a, T> where T: Copy + Debug, { fn new_from_vec(vec: Vec<T>, operation: &'a dyn Fn(&T, &T) -> T) -> Self { let left_index = 0; let right_index = vec.len() - 1; Self::new_from_slice(&vec, left_index, right_index, operation) } fn new_from_slice( slice: &[T], left_index: usize, right_index: usize, operation: &'a dyn Fn(&T, &T) -> T, ) -> Self { if left_index == right_index { SegmentTreeNode { left_node: None, right_node: None, left_index, right_index, info: slice[0], operation, } } else { let mid_index = (left_index + right_index) / 2; let left_node = Self::new_from_slice( &slice[0..=(mid_index - left_index)], left_index, mid_index, operation, ); let right_node = Self::new_from_slice( &slice[(mid_index - left_index + 1)..=(right_index - left_index)], mid_index + 1, right_index, operation, ); let info = operation(&left_node.info, &right_node.info); SegmentTreeNode { left_node: Some(Box::new(left_node)), right_node: Some(Box::new(right_node)), left_index, right_index, info, operation, } } } fn update_index(&mut self, index: usize, info: T) { if self.left_index == index && self.right_index == index { self.info = info; } match (&mut self.left_node, &mut self.right_node) { (Some(left_node), Some(right_node)) => { if left_node.right_index >= index { left_node.update_index(index, info); } else { right_node.update_index(index, info); } self.info = (self.operation)(&left_node.info, &right_node.info); } _ => (), } } fn range_operation(&self, left_index: usize, right_index: usize) -> T { if left_index < self.left_index || right_index > self.right_index { panic!("indexes out of range") } if left_index == self.left_index && right_index == self.right_index { return self.info; } match (&self.left_node, &self.right_node) { (Some(left_node), Some(right_node)) => { if right_index <= left_node.right_index { left_node.range_operation(left_index, right_index) } else if left_index >= right_node.left_index { right_node.range_operation(left_index, right_index) } else { (self.operation)( &left_node.range_operation(left_index, left_node.right_index), &right_node.range_operation(right_node.left_index, right_index), ) } } (Some(left_node), None) => left_node.range_operation(left_index, right_index), (None, Some(right_node)) => right_node.range_operation(left_index, right_index), (None, None) => unreachable!(), } } } struct NumArray<'a> { node: SegmentTreeNode<'a, i32>, } impl NumArray<'_> { fn new(nums: Vec<i32>) -> Self { NumArray { node: SegmentTreeNode::new_from_vec(nums, &|a: &i32, b: &i32| a + b), } } fn update(&mut self, index: i32, val: i32) { self.node.update_index(index as usize, val) } fn sum_range(&self, left: i32, right: i32) -> i32 { self.node.range_operation(left as usize, right as usize) } }

Segment Tree Min Index

use std::{ fmt::Debug, cmp::{Ordering, Reverse}, collections::{BinaryHeap, HashMap, HashSet}, fmt::Binary, hash::Hash, }; fn main() { let target = vec![1,2,3,2,1]; let res = Solution::min_number_operations(target); println!("{:?}", res); } struct Solution; impl Solution { pub fn min_number_operations(target: Vec<i32>) -> i32 { let root = SegmentTreeNode::new_from_vec(&target); Self::dfs(0, target.len() - 1, 0, &root, &target) } fn dfs(left_idx: usize, right_idx:usize, base: i32, root: &SegmentTreeNode, target: &Vec<i32>) -> i32 { if right_idx < left_idx { return 0; } if left_idx == right_idx { return target[left_idx] - base; } let (min_idx, min_val) = root.query_range_min(left_idx, right_idx); let mut res = min_val - base; if min_idx > 0 { res += Self::dfs(left_idx, min_idx - 1, min_val, root, target); } res += Self::dfs(min_idx + 1, right_idx, min_val, root, target); res } } #[derive(Debug)] struct SegmentTreeNode { left_node: Option<Box<SegmentTreeNode>>, right_node: Option<Box<SegmentTreeNode>>, left_index: usize, right_index: usize, min_idx: usize, min_val: i32, } impl SegmentTreeNode{ fn new_from_vec(vec: &Vec<i32>) -> Self { let left_index = 0; let right_index = vec.len() - 1; Self::new_from_slice(&vec, left_index, right_index) } fn new_from_slice( slice: &[i32], left_index: usize, right_index: usize, ) -> Self { if left_index == right_index { SegmentTreeNode { left_node: None, right_node: None, left_index, right_index, min_idx: left_index, min_val: slice[0], } } else { let mid_index = (left_index + right_index) / 2; let left_node = Self::new_from_slice( &slice[0..=(mid_index - left_index)], left_index, mid_index, ); let right_node = Self::new_from_slice( &slice[(mid_index - left_index + 1)..=(right_index - left_index)], mid_index + 1, right_index, ); let (min_idx, min_val) = if left_node.min_val < right_node.min_val { (left_node.min_idx, left_node.min_val) } else { (right_node.min_idx, right_node.min_val) }; SegmentTreeNode { left_node: Some(Box::new(left_node)), right_node: Some(Box::new(right_node)), left_index, right_index, min_idx, min_val, } } } fn query_range_min(&self, left_index: usize, right_index: usize) -> (usize, i32) { if right_index < self.left_index || left_index > self.right_index { (usize::MAX, i32::MAX) } else if left_index <= self.left_index && right_index >= self.right_index { (self.min_idx, self.min_val) } else { let (left_min_idx, left_min_val) = self.left_node.as_ref().unwrap().query_range_min(left_index, right_index); let (right_min_idx, right_min_val) = self.right_node.as_ref().unwrap().query_range_min(left_index, right_index); if left_min_val < right_min_val { (left_min_idx, left_min_val) } else { (right_min_idx, right_min_val) } } } }