#include <bits/stdc++.h>
using namespace std;
ifstream fi("arbint.in");
ofstream fo("arbint.out");
const int N = 1e5 + 5;
int arbint[N * 4];
int n, q, qst, qdr, pos, val;
static void build(int nod, int st, int dr) {
if (st == dr) {
fi >> arbint[nod];
return; }
int mid = (st + dr) / 2;
build(2 * nod, st, mid);
build(2 * nod + 1, mid + 1, dr);
arbint[nod] = max(arbint[2 * nod], arbint[2 * nod + 1]); }
static void update(int nod, int st, int dr) {
if (st == dr) {
arbint[nod] = val;
return; }
int mid = (st + dr) / 2;
if (pos <= mid)
update(2 * nod, st, mid);
else
update(2 * nod + 1, mid + 1, dr);
arbint[nod] = max(arbint[2 * nod], arbint[2 * nod + 1]); }
static void update(int _pos, int _val) {
pos = _pos;
val = _val;
update(1, 1, n); }
static int query(int nod, int st, int dr) {
if (qst <= st && dr <= qdr)
return arbint[nod];
int ant = -1, mid = (st + dr) / 2;
if (qst <= mid)
ant = max(ant, query(2 * nod, st, mid));
if (mid + 1 <= qdr)
ant = max(ant, query(2 * nod + 1, mid + 1, dr));
return ant; }
static int query(int st, int dr) {
qst = st;
qdr = dr;
return query(1, 1, n); }
int main() {
int op, l, r, pos, x;
fi >> n >> q;
build(1, 1, n);
while (q--) {
fi >> op;
switch (op) {
case 0: { // query
fi >> l >> r;
fo << query(l, r) << '\n';
break; }
case 1: { // update
fi >> pos >> x;
update(pos, x);
break; } } }
return 0; }