#include <stdio.h>
#include <stdlib.h>
#define NMAX 100000
int n, m;
int v[NMAX];
int ArbInt[4 * NMAX];
int max (int a, int b)
{
return a < b ? b : a;
}
int inclus (int x1, int y1, int x2, int y2)
{
return x2 <= y1 && x1 >= x2 && y2 >= y1;
}
int intersect (int x1, int y1, int x2, int y2)
{
return x2 <= y1 && x1 <= y2;
}
int build (int nod, int st, int dr)
{
if (dr - st < 1)
{
ArbInt[nod] = v[st];
return v[st];
}
int mid = (st + dr) >> 1;
int vl = build (nod * 2 + 1, st, mid);
int vr = build (nod * 2 + 2, mid + 1, dr);
ArbInt[nod] = max(vl, vr);
return ArbInt[nod];
}
int update (int nod, int st, int dr, int a, int b, int val)
{
if (inclus (st, dr, a, b))
{
ArbInt[nod] = val;
return val;
}
int mid = (st + dr) >> 1;
if (intersect (st, mid, a, b))
update (nod * 2 + 1, st, mid, a, b, val);
if (intersect (mid + 1, dr, a, b))
update (nod * 2 + 2, mid + 1, dr, a, b, val);
ArbInt[nod] = max (ArbInt[nod * 2 + 1], ArbInt[nod * 2 + 2]);
return ArbInt[nod];
}
int query (int nod, int st, int dr, int a, int b)
{
if (inclus (st, dr, a, b))
return ArbInt[nod];
int mid = (st + dr) >> 1;
int p1 = 0, p2 = 0;
if (intersect (st, mid, a, b))
p1 = query (nod * 2 + 1, st, mid, a, b);
if (intersect (mid + 1, dr, a, b))
p2 = query (nod * 2 + 2, mid + 1, dr, a, b);
return max (p1, p2);
}
int main()
{
FILE *in = fopen ("arbint.in", "r");
FILE *out = fopen ("arbint.out", "w");
fscanf (in, "%d%d", &n, &m);
int i;
for (i = 0; i < n; ++i)
fscanf (in, "%d", &v[i]);
build (0, 0, n - 1);
for (i = 0; i < m; ++i)
{
int t, x, y;
fscanf(in, "%d%d%d", &t, &x, &y);
if (t == 0)
fprintf (out, "%d\n", query (0, 0, n - 1, x - 1, y - 1));
if (t == 1)
update (0, 0, n - 1, x - 1, x - 1, y);
}
fclose(in);
fclose(out);
return 0;
}