use std::{
cmp::Ordering::{Equal, Greater, Less},
cmp::max,
fs,
};
struct Node {
value: i64,
maximum: i64, // of the subtree
pos: usize,
left: Subtree,
right: Subtree,
}
struct Subtree(Option<Box<Node>>);
impl Subtree {
pub fn new(nums: &[i64], before: usize) -> Self {
if nums.is_empty() {
Subtree(None)
} else {
let middle = nums.len() / 2;
Subtree(Some(Box::new(Node {
value: nums[middle],
maximum: nums[middle],
pos: before + middle,
left: Subtree::new(&nums[..middle], before),
right: Subtree::new(&nums[middle + 1..], before + middle + 1),
})))
}
}
pub fn calculate_max(&mut self) -> i64 {
match &mut self.0 {
None => 0,
Some(node) => {
let leftmax = node.left.calculate_max();
let rightmax = node.right.calculate_max();
node.maximum = std::cmp::max(node.maximum, std::cmp::max(leftmax, rightmax));
node.maximum
}
}
}
pub fn max(&self) -> i64 {
match &self.0 {
None => 0,
Some(node) => node.maximum,
}
}
pub fn left_query(&self, a: usize) -> i64 {
match &self.0 {
None => 0,
Some(node) => match node.pos.cmp(&a) {
Less => node.right.left_query(a),
Greater => node.left.left_query(a),
Equal => max(node.value, node.right.max()),
},
}
}
pub fn right_query(&self, b: usize) -> i64 {
match &self.0 {
None => 0,
Some(node) => match node.pos.cmp(&b) {
Less => node.right.right_query(b),
Greater => node.left.right_query(b),
Equal => max(node.value, node.left.max()),
},
}
}
pub fn query(&self, a: usize, b: usize) -> i64 {
match &self.0 {
None => 0,
Some(node) => match node.pos.cmp(&a) {
Less => node.right.query(a, b),
Equal => match node.pos.cmp(&b) {
Equal => node.value,
_ => max(node.value, node.right.right_query(b)),
},
Greater => match node.pos.cmp(&b) {
Greater => node.left.query(a, b),
Equal => max(node.value, node.left.left_query(a)),
Less => std::cmp::max(
node.value,
std::cmp::max(node.left.left_query(a), node.right.right_query(b)),
),
},
},
}
}
pub fn update(&mut self, pos: usize, val: i64) {
match &mut self.0 {
None => {}
Some(node) => {
match node.pos.cmp(&pos) {
Equal => {
node.value = val;
node.maximum = val
}
Less => node.right.update(pos, val),
Greater => node.left.update(pos, val),
}
node.maximum = max(node.value, max(node.left.max(), node.right.max()));
}
}
}
}
fn main() {
let input = fs::read_to_string("arbint.in").unwrap();
let content = input
.split_ascii_whitespace()
.map(|s| s.parse::<i64>().unwrap())
.collect::<Vec<i64>>();
let n = content[0] as usize;
let nums = &content[2..n + 2];
let queries = &content[n + 2..];
let mut arbint = Subtree::new(nums, 0);
arbint.calculate_max();
let output: String = queries
.chunks(3)
.map(|q| {
if q[0] == 0 {
format!("{}\n", arbint.query(q[1] as usize - 1, q[2] as usize - 1))
} else {
arbint.update(q[1] as usize - 1, q[2]);
"".to_string()
}
})
.collect();
fs::write("arbint.out", output).unwrap();
}