#include <cstdio>
#include <algorithm>
#define N 100010
using namespace std;
struct nod
{
int val;
nod *T, *S, *D;
nod()
{
val = 0;
T = S = D = NULL;
}
nod(int _v, nod* _T)
{
val = _v;
T = _T;
S = D = NULL;
}
};
nod *root, *fr[N], *build_aint(int, int, nod*);
int a[N], n, m, i, x, y, cod, query(int, int, nod*), upd();
int main()
{
freopen("arbint.in", "r", stdin);
freopen("arbint.out", "w", stdout);
scanf("%d%d", &n, &m);
for(i = 1; i <= n; i++)
scanf("%d", &a[i]);
root = build_aint(1, n, NULL);
for(;m;m--)
{
scanf("%d%d%d", &cod, &x, &y);
if(cod == 0)
printf("%d\n", query(1, n, root));
else
upd();
}
return 0;
}
nod* build_aint(int L, int R, nod* T)
{
nod* ret;
ret=new nod;
if(L == R)
{
ret->val=a[L];
ret->S=ret->D=NULL;
ret->T=T;
fr[L] = ret;
return ret;
}
ret = new nod;
ret->S = build_aint(L, (L+R)/2, ret);
ret->D = build_aint((L+R)/2+1, R, ret);
ret->val = max(ret->S->val, ret->D->val);
ret->T = T;
return ret;
}
int query(int L, int R, nod* X)
{
if(R < x || y < L)
return 0;
if(x <= L && R <= y)
return X->val;
int M = (L+R)/2;
return max(query(L, M, X->S), query(M+1, R, X->D));
}
int upd()
{
nod* aux = fr[x];
aux->val = y;
for(aux = aux->T; aux; aux = aux->T)
aux->val = max(aux->S->val, aux->D->val);
return 0;
}