Cod sursa(job #3151861)

Utilizator TincaMateiTinca Matei TincaMatei Data 23 septembrie 2023 01:37:45
Problema Arbori de intervale Scor 100
Compilator rs Status done
Runda Arhiva educationala Marime 9.11 kb
pub use __cargo_equip::prelude::*;

use dopecomp_io::{InParser, OutParser};

struct SegtreeIterator {
    n: usize,
    query: (usize, usize),
    i: usize,
}

impl SegtreeIterator {
    fn new(n: usize, query: (usize, usize)) -> SegtreeIterator {
        SegtreeIterator { n, query, i: 1 }
    }
}

impl Iterator for SegtreeIterator {
    type Item = (usize, usize, usize);
    fn next(&mut self) -> Option<Self::Item> {
        if self.i == 0 {
            return None;
        }
        let msbpos: usize = 64 - 1 - self.i.leading_zeros() as usize;

        let l = (self.i ^ (1 << msbpos)) << (self.n.trailing_zeros() as usize - msbpos);
        let r = l + (self.n >> msbpos);
        let ret = (self.i, l, r);

        if (self.query.1 <= l || self.query.0 >= r) || (self.query.0 <= l && r <= self.query.1) {
            self.i = (self.i + 1) >> (self.i + 1).trailing_zeros();
        } else {
            self.i = self.i * 2;
        }

        if self.i == 1 {
            self.i = 0;
        }

        Some(ret)
    }
}

#[derive(Debug)]
struct SegmentTree {
    data: Vec<i32>,
}

impl SegmentTree {
    fn new(n: usize, default: i32) -> SegmentTree {
        let msbpos: usize = 64 - 1 - n.leading_zeros() as usize;
        let len: usize = if (1 << msbpos) == n {
            n
        } else {
            1 << (msbpos + 1)
        };

        SegmentTree {
            data: vec![default; len << 1],
        }
    }

    fn from_data(v: &[i32]) -> SegmentTree {
        let mut ret = SegmentTree::new(v.len(), 0);
        let half = ret.data.len() >> 1;

        for (i, &val) in v.iter().enumerate() {
            ret.data[half ^ i] = val;
        }
        for i in (1..half).rev() {
            ret.data[i] = i32::max(ret.data[i << 1], ret.data[(i << 1) ^ 1]);
        }

        ret
    }

    fn update(&mut self, pos: usize, val: i32) {
        SegtreeIterator::new(self.data.len() >> 1, (pos, pos + 1))
            .collect::<Vec<(usize, usize, usize)>>()
            .iter()
            .rev()
            .for_each(|(i, l, r)| {
                if l + 1 == *r && *l == pos {
                    self.data[*i] = val;
                } else if l + 1 < *r {
                    self.data[*i] = i32::max(self.data[i << 1], self.data[(i << 1) ^ 1]);
                }
            })
    }

    fn query(&self, range: (usize, usize)) -> i32 {
        SegtreeIterator::new(self.data.len() >> 1, range).fold(0, |val, (i, l, r)| {
            if range.0 <= l && r <= range.1 {
                i32::max(val, self.data[i])
            } else {
                val
            }
        })
    }
}

fn main() {
    let mut fin = InParser::from_filename("arbint.in");
    let mut fout = OutParser::from_filename("arbint.out");

    let (n, m): (usize, usize) = (fin.read(), fin.read());
    let arr: Vec<i32> = (0..n).map(|_| fin.read::<i32>()).collect();

    let mut segtree = SegmentTree::from_data(&arr);

    for _ in 0..m {
        let t: usize = fin.read();

        if t == 0 {
            let (l, r): (usize, usize) = (fin.read(), fin.read());
            fout.write(segtree.query((l - 1, r)));
            fout.write('\n');
        } else {
            let (pos, val): (usize, i32) = (fin.read(), fin.read());
            segtree.update(pos - 1, val);
        }
    }
}

// The following code was expanded by `cargo-equip`.

///  # Bundled libraries
/// 
///  - `dopecomp_io 0.1.0 (path+███████████████████████████████████████████████████)` published in https://github.com/tincaMatei/competitive-rust licensed under `MIT OR Apache-2.0` as `crate::__cargo_equip::crates::dopecomp_io`
/// 
///  # License and Copyright Notices
/// 
///  - `dopecomp_io 0.1.0 (path+███████████████████████████████████████████████████)`
/// 
///      ```text
///      ```
#[cfg_attr(any(), rustfmt::skip)]
#[allow(unused)]
mod __cargo_equip {
    pub(crate) mod crates {
        pub mod dopecomp_io {#![doc=" Read and write utilities for competitive programming."]#![doc=""]#![doc=" ```"]#![doc=" use std::io::{Cursor, BufReader};"]#![doc=" # use dopecomp_io::InParser;"]#![doc=""]#![doc=" let reader = Cursor::new(b\"1 2 asdf\");"]#![doc=" let mut reader = InParser::new(BufReader::new(reader));"]#![doc=""]#![doc=" assert_eq!(reader.read::<i32>(), 1);"]#![doc=""]#![doc=" let val: i32 = reader.read();"]#![doc=" assert_eq!(val, 2);"]#![doc=""]#![doc=" let val: String = reader.read();"]#![doc=" assert_eq!(val, \"asdf\");"]#![doc=" ```"]#![allow(dead_code)]use std::io::{Read,BufRead,Stdin,BufReader,Write,BufWriter,Stdout};use std::fs::File;use std::str::FromStr;use std::fmt::Debug;#[doc=" Parser used for reading from stdin, files, or any other source."]#[doc=""]#[doc=" ```no_run"]#[doc=" # use dopecomp_io::InParser;"]#[doc=" #"]#[doc=" // stdin:"]#[doc=" //       1      2   asdf"]#[doc=""]#[doc=" let mut reader = InParser::from_stdin();"]#[doc=""]#[doc=" assert_eq!(reader.read::<i32>(), 1);"]#[doc=""]#[doc=" let val: i32 = reader.read();"]#[doc=" assert_eq!(val, 2);"]#[doc=""]#[doc=" let val: String = reader.read();"]#[doc=" assert_eq!(val, \"asdf\");"]#[doc=" ```"]pub struct InParser<T:Read>{reader:BufReader<T>,buffer:Vec<u8>,cursor:usize,eof_flag:bool,}impl InParser<Stdin>{#[doc=" Create a parser from stdin."]pub fn from_stdin()->InParser<Stdin>{InParser::new(std::io::stdin())}}impl InParser<File>{#[doc=" Create a parser from a file specified by the name of the file."]pub fn from_filename(name:&str)->InParser<File>{InParser::new(File::open(name).expect("Failed to open file"))}}impl<T:Read>InParser<T>{#[doc=" Create a parser from any object that implements [Read]."]pub fn new(reader:T)->InParser<T>{let mut reader=BufReader::new(reader);let buffer=reader.fill_buf().expect("Failed to fill buffer").to_vec();InParser{reader,buffer,cursor:0,eof_flag:false,}}#[doc=" Returns the byte at the current position of the cursor or [None] if the"]#[doc=" entire input has been consumed."]pub fn get_current_byte(&mut self)->u8{if self.cursor<self.buffer.len(){return self.buffer[self.cursor];}panic!("Outside of buffer")}#[doc=" Advance the cursor to the next position."]pub fn advance_cursor(&mut self){self.cursor+=1;if self.cursor>=self.buffer.len(){self.reader.consume(self.buffer.len());self.buffer=self.reader.fill_buf().expect("Failed to fill buffer").to_vec();self.eof_flag=self.buffer.is_empty();self.cursor=0;}}fn skip_spaces(&mut self){while!self.eof_flag&&(self.get_current_byte()==b' '||self.get_current_byte()==b'\n'){self.advance_cursor();}}fn get_token(&mut self)->Vec<u8>{let mut token_buf:Vec<u8> =Vec::new();self.skip_spaces();while!self.eof_flag&&self.get_current_byte()!=b' '&&self.get_current_byte()!=b'\n'{let byte=self.get_current_byte();token_buf.push(byte);self.advance_cursor();}token_buf}#[doc=" Read a string from the input."]pub fn read_string(&mut self)->String{let token=self.get_token();let strval=std::str::from_utf8(&token).expect("Failed to convert into valid utf8").trim();strval.to_string()}#[doc=" Read an integer number from the input."]pub fn read_number<F:From<i64>>(&mut self)->F{self.skip_spaces();let sgn=if self.get_current_byte()==b'-'{self.advance_cursor();-1}else{1};let mut nr=0;while!self.eof_flag&&self.get_current_byte().is_ascii_digit(){nr=nr*10+(self.get_current_byte()-b'0')as i64;self.advance_cursor();}F::from(nr*sgn)}#[doc=" Read an element from the input that can be parsed. "]#[doc=""]#[doc=" It is preferred to use"]#[doc=" [InParser::read_number] instead of this function, because the latter is optimized."]#[doc=""]#[doc=" When reading a string, use [InParser::read_string] instead, because there is no parsing"]#[doc=" needed to convert to the required type."]pub fn read<F>(&mut self)->F where F:FromStr,<F as FromStr>::Err:Debug{self.read_string().parse::<F>().unwrap()}}#[doc=" Writer used for writing in stdout, a file, or any other place."]#[doc=" "]#[doc=" ```no_run"]#[doc=" # use dopecomp_io::OutParser;"]#[doc=" #"]#[doc=" let mut writer = OutParser::from_stdout();"]#[doc=""]#[doc=" let x: i32 = 2;"]#[doc=" let y: i32 = 3;"]#[doc=""]#[doc=" writer.write(x)"]#[doc="     .write(\"\\n\")"]#[doc="     .write(format!(\"Sum: {}\\n\", x + y));"]#[doc=""]#[doc=" // stdout:"]#[doc=" // 2"]#[doc=" // 5"]#[doc=""]#[doc=" ```"]pub struct OutParser<T:Write>{writer:BufWriter<T>,}impl<T:Write>OutParser<T>{#[doc=" Create a writer from any item that implements [Write]"]pub fn new(writer:T)->OutParser<T>{OutParser{writer:BufWriter::new(writer)}}#[doc=" Write a value to the target."]pub fn write<F:ToString>(&mut self,val:F)->&mut Self{self.writer.write(&val.to_string().as_bytes()).expect("Failed to write");self}}impl OutParser<Stdout>{#[doc=" Create a writer from stdout."]pub fn from_stdout()->OutParser<Stdout>{OutParser::new(std::io::stdout())}}impl OutParser<File>{#[doc=" Create a writer from a file at the given path."]pub fn from_filename(name:&str)->OutParser<File>{OutParser::new(File::create(name).expect("Failed to open file"))}}}
    }

    pub(crate) mod macros {
        pub mod dopecomp_io {}
    }

    pub(crate) mod prelude {pub use crate::__cargo_equip::crates::*;}

    mod preludes {
        pub mod dopecomp_io {}
    }
}