Cod sursa(job #3311944)

Utilizator sad_carrotVisan Sebastian sad_carrot Data 25 septembrie 2025 00:42:10
Problema Arbori de intervale Scor 100
Compilator rs Status done
Runda Arhiva educationala Marime 4.35 kb
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 => max(node.value, max(node.right.max(), 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 => max(node.value, max(node.left.max(), 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()));
            }
        }
    }
    pub fn print(&self) {
        match &self.0 {
            None => {}
            Some(node) => {
                node.left.print();
                println!("{} v {} m {}", node.pos + 1, node.value, node.maximum);
                node.right.print();
            }
        }
    }
}

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();
}