<?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;
    }
}

Measured memory_bytes: 44064