#![allow(dead_code)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SegTreeOp {
Sum,
Min,
Max,
}
#[derive(Debug, Clone)]
pub struct SegmentTreeV3 {
n: usize,
tree: Vec<i64>,
op: SegTreeOp,
}
impl SegmentTreeV3 {
pub fn build(values: &[i64], op: SegTreeOp) -> Self {
let n = values.len();
let mut tree = vec![identity(op); 2 * n];
tree[n..].copy_from_slice(values);
for i in (1..n).rev() {
tree[i] = combine(tree[2 * i], tree[2 * i + 1], op);
}
SegmentTreeV3 { n, tree, op }
}
pub fn update(&mut self, i: usize, value: i64) {
let mut pos = i + self.n;
self.tree[pos] = value;
pos /= 2;
while pos >= 1 {
self.tree[pos] = combine(self.tree[2 * pos], self.tree[2 * pos + 1], self.op);
if pos == 1 { break; }
pos /= 2;
}
}
pub fn query(&self, lo: usize, hi: usize) -> i64 {
let mut result = identity(self.op);
let mut l = lo + self.n;
let mut r = hi + self.n;
while l < r {
if l & 1 == 1 {
result = combine(result, self.tree[l], self.op);
l += 1;
}
if r & 1 == 1 {
r -= 1;
result = combine(result, self.tree[r], self.op);
}
l /= 2;
r /= 2;
}
result
}
pub fn len(&self) -> usize {
self.n
}
pub fn is_empty(&self) -> bool {
self.n == 0
}
}
fn identity(op: SegTreeOp) -> i64 {
match op {
SegTreeOp::Sum => 0,
SegTreeOp::Min => i64::MAX,
SegTreeOp::Max => i64::MIN,
}
}
fn combine(a: i64, b: i64, op: SegTreeOp) -> i64 {
match op {
SegTreeOp::Sum => a + b,
SegTreeOp::Min => a.min(b),
SegTreeOp::Max => a.max(b),
}
}
pub fn new_seg_tree_sum(values: &[i64]) -> SegmentTreeV3 {
SegmentTreeV3::build(values, SegTreeOp::Sum)
}
pub fn new_seg_tree_min(values: &[i64]) -> SegmentTreeV3 {
SegmentTreeV3::build(values, SegTreeOp::Min)
}
pub fn new_seg_tree_max(values: &[i64]) -> SegmentTreeV3 {
SegmentTreeV3::build(values, SegTreeOp::Max)
}
pub fn st3_update(tree: &mut SegmentTreeV3, i: usize, value: i64) {
tree.update(i, value);
}
pub fn st3_query(tree: &SegmentTreeV3, lo: usize, hi: usize) -> i64 {
tree.query(lo, hi)
}
pub fn st3_len(tree: &SegmentTreeV3) -> usize {
tree.len()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_sum_query() {
let t = new_seg_tree_sum(&[1, 2, 3, 4, 5]);
assert_eq!(st3_query(&t, 0, 5), 15 );
}
#[test]
fn test_sum_partial() {
let t = new_seg_tree_sum(&[1, 2, 3, 4, 5]);
assert_eq!(st3_query(&t, 1, 4), 9 );
}
#[test]
fn test_min_query() {
let t = new_seg_tree_min(&[5, 3, 8, 1, 7]);
assert_eq!(st3_query(&t, 0, 5), 1 );
}
#[test]
fn test_max_query() {
let t = new_seg_tree_max(&[5, 3, 8, 1, 7]);
assert_eq!(st3_query(&t, 0, 5), 8 );
}
#[test]
fn test_update() {
let mut t = new_seg_tree_sum(&[1, 2, 3]);
st3_update(&mut t, 1, 10);
assert_eq!(st3_query(&t, 0, 3), 14 );
}
#[test]
fn test_len() {
let t = new_seg_tree_sum(&[1, 2, 3, 4]);
assert_eq!(st3_len(&t), 4 );
}
#[test]
fn test_single_element() {
let t = new_seg_tree_sum(&[42]);
assert_eq!(st3_query(&t, 0, 1), 42 );
}
#[test]
fn test_min_range() {
let t = new_seg_tree_min(&[10, 3, 7, 2, 9]);
assert_eq!(st3_query(&t, 2, 5), 2 );
}
#[test]
fn test_max_range() {
let t = new_seg_tree_max(&[1, 5, 2, 8, 3]);
assert_eq!(st3_query(&t, 1, 4), 8 );
}
#[test]
fn test_update_min() {
let mut t = new_seg_tree_min(&[5, 10, 15]);
st3_update(&mut t, 0, 1);
assert_eq!(st3_query(&t, 0, 3), 1 );
}
}