Problem:
Score : 100 points

Problem Statement

You are given an array a_0, a_1, ..., a_{N-1} of length N. Process Q queries of the following types.

The type of i-th query is represented by T_i.

T_i=1: You are given two integers X_i,V_i. Replace the value of A_{X_i} with V_i.

T_i=2: You are given two integers L_i,R_i. Calculate the maximum value among A_{L_i},A_{L_i+1},\cdots,A_{R_i}.

T_i=3: You are given two integers X_i,V_i. Calculate the minimum j such that X_i \leq j \leq N, V_i \leq A_j. If there is no such j, answer j=N+1 instead.

Constraints

1 \leq N \leq 2 \times 10^5

0 \leq A_i \leq 10^9

1 \leq Q \leq 2 \times 10^5

1 \leq T_i \leq 3

1 \leq X_i \leq N, 0 \leq V_i \leq 10^9 (T_i=1,3)

1 \leq L_i \leq R_i \leq N (T_i=2)

All values in Input are integer.

Input

Input is given from Standard Input in the following format:

N Q
A_1 A_2 \cdots A_N
First query
Second query
\vdots
Q-th query

Each query is given in the following format:

If T_i=1,3,

T_i X_i V_i

If T_i=2,

T_i L_i R_i

Output

For each query with T_i=2, 3, print the answer.

Sample Input 1

5 5
1 2 3 2 1
2 1 5
3 2 3
1 3 1
2 2 4
3 1 3

Sample Output 1

3
3
2
6

First query: Print 3, which is the maximum of (A_1,A_2,A_3,A_4,A_5)=(1,2,3,2,1).

Second query: Since 3>A_2, j=2 does not satisfy the condition．Since 3 \leq A_3, print j=3.

Third query: Replace the value of A_3 with 1. It becomes A=(1,2,1,2,1).

Fourth query: Print 2, which is the maximum of (A_2,A_3,A_4)=(2,1,2).

Fifth query: Since there is no j that satisfies the condition, print j=N+1=6.

Solution in Rust (1.42.0) (judge verdict: Accepted)

//---------- begin SegmentTree Point update Range query ----------
pub trait PURQ {
    type T: Clone;
    fn fold(l: &Self::T, r: &Self::T) -> Self::T;
    fn e() -> Self::T;
}

struct SegmentTreePURQ<R: PURQ> {
    seg: Vec<R::T>,
    size: usize,
}

#[allow(dead_code)]
impl<R: PURQ> SegmentTreePURQ<R> {
    fn new(n: usize) -> SegmentTreePURQ<R> {
        let size = n.next_power_of_two();
        SegmentTreePURQ {
            seg: vec![R::e(); 2 * size],
            size: size,
        }
    }
    fn build_by(a: &[R::T]) -> SegmentTreePURQ<R> {
        let size = a.len().next_power_of_two();
        let mut b = vec![R::e(); 2 * size];
        for i in 0..a.len() {
            b[i + size] = a[i].clone();
        }
        let mut seg = SegmentTreePURQ { seg: b, size: size };
        seg.update_all();
        seg
    }
    fn update(&mut self, x: usize, v: R::T) {
        assert!(x < self.size);
        let mut x = x + self.size;
        let a = &mut self.seg;
        a[x] = v;
        x >>= 1;
        while x > 0 {
            a[x] = R::fold(&a[2 * x], &a[2 * x + 1]);
            x >>= 1;
        }
    }
    fn update_tmp(&mut self, x: usize, v: R::T) {
        self.seg[self.size + x] = v;
    }
    fn update_all(&mut self) {
        let a = &mut self.seg;
        for i in (1..self.size).rev() {
            a[i] = R::fold(&a[2 * i], &a[2 * i + 1]);
        }
    }
    fn find(&self, l: usize, r: usize) -> R::T {
        assert!(l <= r && r <= self.size);
        let mut x = R::e();
        let mut y = R::e();
        let mut l = l + self.size;
        let mut r = r + self.size;
        let a = &self.seg;
        while l < r {
            if l & 1 == 1 {
                x = R::fold(&x, &a[l]);
                l += 1;
            }
            if r & 1 == 1 {
                r -= 1;
                y = R::fold(&a[r], &y);
            }
            l >>= 1;
            r >>= 1;
        }
        R::fold(&x, &y)
    }
    // f(a[l..k]) がkについてfalse, false, ..., true みたいに単調であるとした時
    // 戻り値Some(x)は
    // f(&a[l..x]) = false
    // f(&a[l..=x]) = true
    // を満たす
    fn search_right<F>(&self, l: usize, f: F) -> Option<usize>
    where
        F: Fn(&R::T) -> bool,
    {
        let a = &self.seg;
        let mut v = R::e();
        let mut r = self.size * 2;
        let mut l = l + self.size;
        while l < r {
            if l & 1 == 1 {
                let u = R::fold(&v, &a[l]);
                if f(&u) {
                    break;
                }
                l += 1;
                v = u;
            }
            l >>= 1;
            r >>= 1;
        }
        if l == r {
            return None;
        }
        let mut x = l;
        while x < self.size {
            x <<= 1;
            let u = R::fold(&v, &a[x]);
            if !f(&u) {
                x += 1;
                v = u;
            }
        }
        Some(x - self.size)
    }
}
//---------- end SegmentTree Point update Range query ----------

use proconio::marker::*;
use proconio::*;

struct RMQ;
impl PURQ for RMQ {
    type T = i32;
    fn fold(l: &Self::T, r: &Self::T) -> Self::T {
        std::cmp::max(*l, *r)
    }
    fn e() -> Self::T {
        -1
    }
}

#[fastout]
fn run() {
    input! {
        n: usize,
        q: usize,
        a: [i32; n],
        ask: [(u8, Usize1, i32); q],
    }
    let mut seg = SegmentTreePURQ::<RMQ>::build_by(&a);
    for (op, a, b) in ask {
        match op {
            1 => {
                let x = a;
                let v = b;
                seg.update(x, v);
            },
            2 => {
                let l = a;
                let r = b as usize;
                let ans = seg.find(l, r);
                println!("{}", ans);
            },
            3 => {
                let x = a;
                let v = b;
                let k = seg.search_right(x, |p| *p >= v);
                if let Some(k) = k {
                    println!("{}", k + 1);
                } else {
                    println!("{}", n + 1);
                }
            },
            _ => unreachable!(),
        }
    }
}

fn main() {
    run();
}