//
// main.c
// arbint
//
// Created by Alexandru Bâgu on 12/9/13.
// Copyright (c) 2013 Alexandru Bâgu. All rights reserved.
//
#include <stdio.h>
int tPow(int);
int update(int, int, int, int*);
void query(int, int, int, int, int, int*, int*);
int max(int,int);
int main(int argc, const char * argv[])
{
const int MAX_N = 1000001;
const int MAX_T = (1 << 11) + MAX_N;
freopen("arbint.in", "r", stdin);
freopen("arbint.out", "w", stdout);
int T[MAX_T], n, m;
scanf("%d %d", &n, &m);
int i, treeDepth = tPow(n) + n;
for(i = 0; i < treeDepth; i++)
T[i] = 0;
for(i = 1; i <= n; i++)
{
int v;
scanf("%d", &v);
update(i, v, n, T);
}
for(i = 0; i < m; i++)
{
int a, b, c;
scanf("%d %d %d", &a, &b, &c);
if(a == 0)
{
int maxim = -1;
query(1, 1, n, b, c, T, &maxim);
printf("%d\n", maxim);
}
else
{
update(b, c, n, T);
}
}
return 0;
}
int tPow(int v)
{
int a = 1;
while(a < v) a<<=1;
return 1;
}
int update(int index, int value, int N, int T[])
{
int n = 1, l = 1, r = N, mid;
while(l != r)
{
mid = (l + r) / 2;
if(index <= mid)
{
r = mid;
n *= 2;
}
else
{
l = mid + 1;
n = n * 2 + 1;
}
}
T[n] = value;
while(n >= 1)
{
n /= 2;
T[n] = max(T[n * 2], T[n * 2 + 1]);
}
return 0;
}
void query(int nod, int left, int right, int start, int finish, int T[], int* maxim)
{
if ( start <= left && right <= finish )
{
if ( *maxim < T[nod] ) *maxim = T[nod];
return;
}
int div = (left+right)/2;
if ( start <= div ) query(2*nod,left,div, start, finish, T, maxim);
if ( div < finish ) query(2*nod+1,div+1,right, start, finish, T, maxim);
}
int max(int a, int b)
{
if(a > b) return a;
return b;
}