#include <stdio.h>
#include <algorithm>
using namespace std;
#define UPDATE 1
#define QUERY 0
#define MAX_N 100000
int v[MAX_N];
int vLength;
int aint[MAX_N * 2 - 1];
void build(int node, int nLeft, int nRight) {
if (nLeft == nRight) {
aint[node] = v[nLeft];
return;
}
int nMid, leftSon, rightSon;
nMid = (nLeft + nRight) / 2;
leftSon = node * 2 + 1;
rightSon = leftSon + 1;
build(leftSon, nLeft, nMid);
build(rightSon, nMid + 1, nRight);
aint[node] = max(aint[leftSon], aint[rightSon]);
}
void update(int node, int nLeft, int nRight, int pos, int value) {
if (nLeft == nRight) {
aint[node] = value;
return;
}
int nMid, leftSon, rightSon;
nMid = (nLeft + nRight) / 2;
leftSon = node * 2 + 1;
rightSon = leftSon + 1;
if (pos <= nMid)
update(leftSon, nLeft, nMid, pos, value);
else
update(rightSon, nMid + 1, nRight, pos, value);
aint[node] = max(aint[leftSon], aint[rightSon]);
}
int query(int node, int nLeft, int nRight, int qLeft, int qRight) {
if (qLeft <= nLeft && qRight >= nRight)
return aint[node];
int nMid, leftSon, rightSon;
int result;
nMid = (nLeft + nRight) / 2;
leftSon = node * 2 + 1;
rightSon = leftSon + 1;
result = 0;
if (qLeft <= nMid)
result = query(leftSon, nLeft, nMid, qLeft, qRight);
if (nMid < qRight)
result = max(result, query(rightSon, nMid + 1, nRight, qLeft, qRight));
return result;
}
int main() {
FILE *fin, *fout;
fin = fopen("arbint.in", "r");
fout = fopen("arbint.out", "w");
int i, q, op, a, b;
fscanf(fin, "%d%d", &vLength, &q);
for (i = 0; i < vLength; ++i)
fscanf(fin, "%d", &v[i]);
build(0, 0, vLength - 1);
while (q--) {
fscanf(fin, "%d%d%d", &op, &a, &b);
if (op == UPDATE)
update(0, 0, vLength - 1, a - 1, b);
else if (op == QUERY)
fprintf(fout, "%d\n", query(0, 0, vLength - 1, a - 1, b - 1));
}
fclose(fin);
fclose(fout);
return 0;
}