//arbori de intervale
#include <stdio.h>
#include <values.h>
#define Nmax 100001
int v[Nmax], tree[5*Nmax], x, y, z, n, m, i;
void buildTree(int,int,int);
int Q(int,int);
void U(int,int);
inline int max(int x, int y) { return x>y?x:y; }
int main()
{
freopen("arbint.in", "r", stdin);
scanf("%d %d\n", &n, &m);
for (i=1; i<=n; i++) scanf("%d ", &v[i]);
buildTree(1,1,n);
freopen("arbint.out", "w", stdout);
for(; m; m--)
{
scanf("%d %d %d", &x, &y, &z);
if (!x) printf("%d\n",Q(y,z));
else U(y,z);
}
fclose(stdout);
return 0;
}
void buildTree(int loc, int st, int dr)
{
if (st==dr) { tree[loc]=v[st]; return ; }
else
{
buildTree(loc<<1, st, (st+dr) >> 1);
buildTree((loc<<1) + 1, ((st+dr)>>1) + 1, dr);
tree[loc]=max(tree[loc<<1],tree[(loc<<1) + 1]);
}
}
int Q(int st, int dr)
{
if (st>dr) return -MAXINT;
int p=1, q=n, loc=1;
while (p!=st)
{
if ( (p+q) >> 1 < st )
{
p=((p+q) >> 1) + 1;
loc=(loc << 1) + 1;
}
else
{
q=(p+q) >> 1;
loc<<=1;
}
}
while (q>dr)
{
q=(p+q)>>1;
loc<<=1;
}
return max(tree[loc],Q(q+1,dr));
}
void U(int a, int b)
{
int st=1, dr=n, loc=1;
while (a!=st && st!=dr)
{
if ((st+dr)>>1 < a)
{
st=((st+dr)>>1) + 1;
loc=(loc<< 1) + 1;
}
else
{
dr=(st+dr) >> 1;
loc=loc<<1;
}
}
tree[loc]=b;
while (loc!=1)
{
loc>>=1;
tree[loc]=max(tree[loc<<1], tree[(loc<<1) + 1]);
}
}