output_description: For each query with T_i=2, 3, print the answer.
  
  * * *
input_description: 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
attempt: #!/usr/bin/env python3
  import sys
  
  sys.setrecursionlimit(10**6)
  INF = 10**9 + 1  # sys.maxsize # float("inf")
  MOD = 10**9 + 7
  
  
  def debug(*x):
      print(*x, file=sys.stderr)
  
  
  # Segment Tree
  
  
  def set_depth(depth):
      global DEPTH, SEGTREE_SIZE, NONLEAF_SIZE
      DEPTH = depth
      SEGTREE_SIZE = 1 << DEPTH
      NONLEAF_SIZE = 1 << (DEPTH - 1)
  
  
  def set_width(width):
      global WIDTH
      WIDTH = width
      set_depth((width - 1).bit_length() + 1)
  
  
  def point_set(table, pos, value, binop):
      pos = pos + NONLEAF_SIZE
      table[pos] = value
      while pos > 1:
          pos >>= 1
          table[pos] = binop(
              table[pos * 2],
              table[pos * 2 + 1],
          )
  
  
  def range_reduce(table, left, right, binop, unity):
      ret_left = unity
      ret_right = unity
      left += SEGTREE_SIZE // 2
      right += SEGTREE_SIZE // 2
      while left < right:
          if left & 1:
              ret_left = binop(ret_left, table[left])
              left += 1
          if right & 1:
              right -= 1
              ret_right = binop(table[right], ret_right)
  
          left //= 2
          right //= 2
      return binop(ret_left, ret_right)
  
  
  def bisect_left(table, left, right, value):
      left += NONLEAF_SIZE
      right += NONLEAF_SIZE
      left_left = None
      right_left = None
      while left < right:
          if left & 1:
              if left_left is None and table[left] >= value:
                  left_left = left
              left += 1
          if right & 1:
              if table[right - 1] >= value:
                  right_left = right - 1
          left >>= 1
          right >>= 1
  
      if left_left is not None:
          pos = left_left
          while pos < NONLEAF_SIZE:
              if table[2 * pos] >= value:
                  pos = 2 * pos
              else:
                  pos = 2 * pos + 1
          return pos - NONLEAF_SIZE
      elif right_left is not None:
          pos = right_left
          while pos < NONLEAF_SIZE:
              if table[2 * pos] >= value:
                  pos = 2 * pos
              else:
                  pos = 2 * pos + 1
          return pos - NONLEAF_SIZE
      else:
          return WIDTH
  
  
  def full_up(table, binop):
      for i in range(NONLEAF_SIZE - 1, 0, -1):
          table[i] = binop(table[2 * i], table[2 * i + 1])
  
  
  def main():
      N, Q = map(int, input().split())
      AS = list(map(int, input().split()))
      set_width(N)
  
      table = [0] * SEGTREE_SIZE
      table[NONLEAF_SIZE : NONLEAF_SIZE + len(AS)] = AS
      full_up(table, max)
  
      for _q in range(Q):
          q, x, y = map(int, input().split())
          if q == 1:
              # update
              point_set(table, x - 1, y, max)
          elif q == 2:
              # find
              print(range_reduce(table, x - 1, y, max, -INF))
          else:
              print(bisect_left(table, x - 1, N, y) + 1)
  
  
  # tests
  T1 = """
  5 5
  1 2 3 2 1
  2 1 5
  3 2 3
  1 3 1
  2 2 4
  3 1 3
  """
  TEST_T1 = """
  >>> as_input(T1)
  >>> main()
  3
  3
  2
  6
  """
  
  
  def _test():
      import doctest
  
      doctest.testmod()
      g = globals()
      for k in sorted(g):
          if k.startswith("TEST_"):
              doctest.run_docstring_examples(g[k], g, name=k)
  
  
  def as_input(s):
      "use in test, use given string as input file"
      import io
  
      f = io.StringIO(s.strip())
      g = globals()
      g["input"] = lambda: bytes(f.readline(), "ascii")
      g["read"] = lambda: bytes(f.read(), "ascii")
  
  
  input = sys.stdin.buffer.readline
  read = sys.stdin.buffer.read
  
  if sys.argv[-1] == "-t":
      print("testing")
      _test()
      sys.exit()
  
  main()
  
problem_description: 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.
samples: [{"input": "5 5\n    1 2 3 2 1\n    2 1 5\n    3 2 3\n    1 3 1\n    2 2 4\n    3 1 3", "output": "3\n    3\n    2\n    6\n    \n\n  * First query: Print 3, which is the maximum of (A_1,A_2,A_3,A_4,A_5)=(1,2,3,2,1).\n  * Second query: Since 3>A_2, j=2 does not satisfy the condition\uff0eSince 3 \\leq A_3, print j=3.\n  * Third query: Replace the value of A_3 with 1. It becomes A=(1,2,1,2,1).\n  * Fourth query: Print 2, which is the maximum of (A_2,A_3,A_4)=(2,1,2).\n  * Fifth query: Since there is no j that satisfies the condition, print j=N+1=6."}]