class SegmentTree
  def initialize(arg, e)
    if arg.is_a?(Integer)
      v = Array.new(arg){ e }
    elsif arg.is_a?(Array)
      v = arg
    end

    @e  = e
    @op = Proc.new { yield(_1, _2) }

    @n = v.size
    @log = ceil_pow2(@n)
    @leaf_size = 1 << @log
    @d = Array.new(@leaf_size * 2) { e }
    v.each_with_index { |v_i, i| @d[@leaf_size + i] = v_i }
    (@leaf_size - 1).downto(1) { |i| update(i) }
    self
  end

  def set(q, x)
    q += @leaf_size
    @d[q] = x
    1.upto(@log) { |i| update(q >> i) }
  end

  def get(q)
    d[leaf_size + q]
  end

  def prod(l, r)
    sml = @e
    smr = @e
    l += @leaf_size
    r += @leaf_size

    while l < r
      if l[0] == 1
        sml = @op.call(sml, @d[l])
        l += 1
      end
      if r[0] == 1
        r -= 1
        smr = @op.call(@d[r], smr)
      end
      l /= 2
      r /= 2
    end

    @op.call(sml, smr)
  end

  def all_prod
    d[1]
  end

  def max_right(l)
    return @n if l == @n

    f = Proc.new { yield(_1) }

    l += @leaf_size
    sm = @e
    loop do
      break
      l /= 2 while l.even?
      unless f.call(@op.call(sm, @d[l]))
        while l < @leaf_size
          l *= 2
          if f.call(@op.call(sm, @d[l]))
            sm = op(sm, @d[l])
            l += 1
          end
        end
        return l - @leaf_size
      end
      sm = @op.call(sm, @d[l])
      l += 1
      break if (l & -l) == l
    end

    @n
  end

  private

  def update(k)
    @d[k] = @op.call(@d[2 * k], @d[2 * k + 1])
  end
end

def ceil_pow2(n)
  x = 0
  x += 1 while (1 << x) < n
  x
end

SegTree = SegmentTree
Segtree = SegmentTree

INF = (1 << 60) - 1

n, q = gets.to_s.split.map{ |t| t.to_i }
a    = gets.to_s.split.map{ |t| t.to_i }

st = Segtree.new(a, -INF) { [_1, _2].max }

q.times do
  query = gets.to_s.split.map{ |t| t.to_i }
  if query[0] == 1
    _, x, v = query
    st.set(x - 1, v)
  elsif query[0] == 2
    _, l, r = query
    puts st.prod(l - 1, r)
  else
    _, x, v = query
    puts st.max_right(x - 1) { _1 < v } + 1
  end
end
