#include<stdio.h>
#include<algorithm>
using namespace std;
#define MAXD 18
struct arbore
{
int st, dr, val;
};
arbore v[(1 << MAXD) + 10];
FILE *in, *out;
int genint (int poz, int a, int b)
{
v[poz].st = a;
v[poz].dr = b;
if(b > a) {
genint(poz * 2, a, (a + b) / 2);
genint(poz * 2 + 1, ((a + b) / 2) + 1, b);
}
}
void update(int elem, int val, int poz)
{
if(v[poz].st == v[poz].dr && v[poz].dr == elem) {
v[poz].val = val;
return;
}
if(elem <= v[poz * 2].dr ) {
update(elem, val, poz * 2);
}
if(elem >= v[poz * 2 + 1].st) {
update(elem, val, poz * 2 + 1);
}
v[poz].val = max(v[poz * 2].val, v[poz * 2 + 1].val);
}
int que(int a, int b, int poz)
{
//printf("%d %d %d\n", a, b, poz);
fflush(stdout);
if((a == v[poz].st) && (b == v[poz].dr)) {
return v[poz].val;
}
if(v[poz * 2].dr >= b) {
return que(a, b, poz * 2);
}
if(v[(poz * 2) + 1].st <= a) {
return que(a, b, (poz * 2) + 1);
}
return max(que(a, v[poz * 2].dr, poz * 2), que(v[(poz * 2) + 1].st, b, (poz * 2) + 1));
}
int main ()
{
int n, t, op, a, b, i;
in = fopen("arbint.in", "r");
out = fopen("arbint.out", "w");
fscanf(in, "%d%d", &n, &t);
genint(1, 1, (1 << (MAXD - 1)));
for(i = 1; i <= n; i++) {
fscanf(in, "%d", &a);
update(i, a, 1);
}
/*
for(i = 1; i < 32; i++) {
printf("%d %d %d\n", v[i].val, v[i].st, v[i].dr);
} printf("\n");
*/
for(i = 1; i <= t; i++) {
fscanf(in, "%d%d%d", &op, &a, &b);
if(op == 1) {
update(a, b, 1);
} else {
fprintf(out, "%d\n", que(a, b, 1));
}
}
/*
for(i = 1; i < 32; i++) {
printf("%d %d %d\n", v[i].val, v[i].st, v[i].dr);
}
*/
fclose(in);
fclose(out);
return 0;
}