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 PHP (7.4.4) (judge verdict: Accepted)

<?php

/**
 * Class SegmentTree
 */
class SegmentTree
{


    private $tree = [];
    private int $leaf_size = 0;
    private int $tree_size = 0;
    private $default;
    private object $operation;
    private $t = [0xFFFFFFFF00000000,
        0x00000000FFFF0000,
        0x000000000000FF00,
        0x00000000000000F0,
        0x000000000000000C,
        0x0000000000000002];

    /**
     * SegmentTree constructor.
     * @param int|array $sv treeのサイズもしくは初期値配列
     * @param object $op 2値比較演算子
     * @param int $e 単位元
     */
    function __construct($sv, callable $op, $e=0)
    {
        if(gettype($sv) === "integer"){
            $count = $sv;
            $list = array_fill(0, $count, $e);
        }elseif(gettype($sv) === "array"){
            $count = count($sv);
            $list = $sv;
        }else{
            $count = 0;
            $list = [];
        }
        $this->default = $e;
        $this->operation = $op;
        $this->real_size = $count;
        $this->leaf_size = 2 ** $this->ceil_log2($count);
        $this->tree_size = $this->leaf_size * 2 - 1;
        $this->tree = [...array_fill(0,$this->leaf_size-1, $this->default),
            ...$list,
            ...array_fill(0, $this->leaf_size - $count, $this->default)];

        $this->updateAll();
    }

    /**
     * 値を更新する。配列の添え字は1スタート
     * @param int $target
     * @param $value
     */
    public function update(int $target, $value)
    {
        $target = $target + $this->leaf_size - 2;
        $this->tree[$target] = $value;
        $this->updateUP(($target - 1) >> 1);

    }

    private function updateUP(int $target)
    {

//        while($target >=0){
//            $this->tree[$target] = $this->ev($this->tree[($target << 1) + 1], $this->tree[($target <<1) + 2]);
//            $target-=1;
//            $target>>=1;
//        }
        $this->tree[$target] = ($this->operation)($this->tree[($target << 1) + 1], $this->tree[($target << 1) + 2]);
        if ($target != 0) {
            $this->updateUP(($target - 1) >> 1);
        }
    }

    private function updateAll()
    {
        for ($i = $this->leaf_size - 2; $i >= 0; $i--) {
            $this->tree[$i] = ($this->operation)($this->tree[$i * 2 + 1], $this->tree[$i * 2 + 2]);
        }
    }

    /**
     * op(a[0], ..., a[n - 1]) を計算します。n=0 のときは e() を返します。
     * @return mixed
     */
    public function prod_all()
    {
        return $this->tree[0];
    }


    /**
     * op(a[l], ..., a[r]) を、モノイドの性質を満たしていると仮定して計算します。
     * 添え字は1スタート
     * @param int $from
     * @param int $to
     * @return int|mixed
     */
    public function prod(int $from, int $to ){
        return $this->query($from, $to, 0, 1, $this->leaf_size);
    }


    function query($from, $to, $node, $node_from, $node_to)
    {

        if ($node_from > $to || $node_to < $from) {
            return $this->default;
        }
        if ($node_to <= $to && $node_from >= $from) {
            return $this->tree[$node];
        } else {
            $left = $this->query($from, $to, 2 * $node + 1, $node_from, intdiv($node_from + $node_to, 2));
            $right = $this->query($from, $to, 2 * $node + 2, intdiv($node_from + $node_to, 2) + 1, $node_to);
            return ($this->operation)($left, $right);
        }


    }

    /**
     * 以下の条件を両方満たす r を(いずれか一つ)返します。
     * r = l もしくは f(op(a[l], a[l + 1], ..., a[r - 1])) = true
     * r = n もしくは f(op(a[l], a[l + 1], ..., a[r])) = false
     * fが単調だとすれば、f(op(a[l], a[l + 1], ..., a[r - 1])) = true となる最大の r、と解釈することが可能です。
     * 添え字は1スタート
     * @param int $l
     * @param callable $fn 評価関数
     * @return int
     */
    public function max_right(int $l, callable $fn): int
    {
        if($l === $this->leaf_size){
            return $this->leaf_size;
        }
        $l += $this->leaf_size - 2;
        $sm = $this->default;
        do {
            while ($l % 2 === 1) {
                $l >>= 1;
            }
            if (!$fn(($this->operation)($sm,$this->tree[$l]))) {
                while ($l < ($this->leaf_size-1)) {
                    $l *= 2;
                    $l += 1;
                    if ($fn(($this->operation)($sm, $this->tree[$l]))) {
                        $sm = ($this->operation)($sm, $this->tree[$l]);
                        $l++;
                    }
                }
                return $l - $this->leaf_size + 2;
            }
            $sm = ($this->operation)($sm, $this->tree[$l]);
            $l++;

        } while ((($l + 1) & -($l + 1)) !== ($l + 1));
        return $this->real_size + 1;
    }

    /**
     * 以下の条件を両方満たす l を(いずれか一つ)返します。
     * l = r もしくは f(op(a[l], a[l + 1], ..., a[r - 1])) = true
     * l = 0 もしくは f(op(a[l - 1], a[l + 1], ..., a[r - 1])) = false
     * fが単調だとすれば、f(op(a[l], a[l + 1], ..., a[r - 1])) = true となる最小の l、と解釈することが可能です。
     * 制約
     * fを同じ引数で呼んだ時、返り値は等しい(=副作用はない)
     * f(e()) = true
     * 0≤r≤n
     * 計算量
     * O(logn)
     * @param int $r
     * @param callable $fn
     * @return int
     */
    public function min_left(int $r, callable $fn): int
    {
        if($r === 0){
            return 0;
        }
        $r += $this->leaf_size - 1;
        $sm = $this->default;
        do {
            while ($r % 2 === 0 && $r > 0) {
                $r >>= 1;
            }
            if (!$fn(($this->operation)($sm,$this->tree[$r]))) {
                while ($r < ($this->leaf_size-1)) {
                    $r *= 2;
                    $r += 2;
                    if ($fn(($this->operation)($sm, $this->tree[$r]))) {
                        $sm = ($this->operation)($sm, $this->tree[$r]);
                        $r--;
                    }
                }
                return $r - $this->leaf_size + 2;
            }
            $sm = ($this->operation)($sm, $this->tree[$r]);


        } while ((($r + 1) & -($r + 1)) !== ($r + 1));
        return 0;
    }

    private function ceil_log2(int $x):int
    {
        $y = ((($x & ($x - 1)) == 0) ? 0 : 1);
        $j = 32;
        foreach ($this->t as $value) {
            $k = ((($x & $value) == 0) ? 0 : $j);
            $y += $k;
            $x >>= $k;
            $j >>= 1;
        }
        return $y;
    }
}


[$N, $Q] = fscanf(STDIN, "%d%d");
$A = fscanf(STDIN, str_repeat("%d", $N));
$fn = fn($x, $y) => max($x, $y);
$st = new SegmentTree($A,$fn,0);
while($Q--){
    [$T, $X, $V] = fscanf(STDIN, "%d%d%d");
    if($T === 1){
        $st->update($X, $V);
    }elseif($T === 2){
        echo $st->prod($X,$V).PHP_EOL;
    }else{
        $f = fn($x) =>$x < $V;
        echo $st->max_right($X,$f).PHP_EOL;
    }
}