use std::fmt::Display;
use std::fs::File;
use std::io::*;
struct SegTree<T> {
n: usize,
tree: Vec<T>,
}
impl<T : Default + Clone + Copy + Ord + Display> SegTree<T> {
fn new(n: usize) -> SegTree<T> {
SegTree {
n,
tree: vec![T::default(); 4 * n],
}
}
fn update(&mut self, node: usize, l: usize, r: usize, pos: usize, val: T) {
if l == r {
self.tree[node] = val;
return;
}
let mid = (l + r) / 2;
if pos <= mid {
self.update(2 * node, l, mid, pos, val);
}
else {
self.update(2 * node + 1, mid + 1, r, pos, val);
}
self.tree[node] = self.tree[2 * node].max(self.tree[2 * node + 1]);
// println!("Max on segment {}, {} is {}", l, r, self.tree[node]);
}
fn update_pos(&mut self, pos: usize, val: T) {
self.update(1, 0, self.n - 1, pos, val);
}
fn query(&self, node: usize, l: usize, r: usize, ql: usize, qr: usize) -> T {
if ql <= l && r <= qr { return self.tree[node]; }
let mid = (l + r) / 2;
let mut ans = T::default();
if ql <= mid {
ans = ans.max(self.query(2 * node, l, mid, ql, qr));
}
if mid < qr {
ans = ans.max(self.query(2 * node + 1, mid + 1, r, ql, qr));
}
ans
}
fn query_segment(&self, ql: usize, qr: usize) -> T {
return self.query(1, 0, self.n - 1, ql, qr);
}
}
fn main() {
let in_file = File::open("arbint.in").unwrap();
let out_file = File::create("arbint.out").unwrap();
let mut input = BufReader::new(in_file);
let mut output = BufWriter::new(out_file);
let mut line = String::new();
input.read_line(&mut line).unwrap();
let stuff: Vec<usize> = line.split_whitespace().map(|x| x.parse().unwrap()).collect();
let (n, q) = (stuff[0], stuff[1]);
// println!("n = {}, q = {}", n, q);
line.clear();
input.read_line(&mut line).unwrap();
let v: Vec<i32> = line.split_whitespace().map(|x| x.parse().unwrap()).collect();
let mut seg_tree: SegTree<i32> = SegTree::new(n);
for (i, x) in v.into_iter().enumerate() {
seg_tree.update_pos(i, x);
// println!("v[{}] = {}", i, x);
}
for _i in 0..q {
line.clear();
input.read_line(&mut line).unwrap();
let query: Vec<usize> = line.split_whitespace().map(|x| x.parse().unwrap()).collect();
let (query_type, a, b) = (query[0], query[1], query[2]);
if query_type == 0 {
writeln!(output, "{}", seg_tree.query_segment(a - 1, b - 1)).unwrap();
}
else {
seg_tree.update_pos(a - 1, b as i32);
}
}
}