// vim: tabstop=2:shiftwidth=2:expandtab:syntax=off
#include <cstdio>
#include <algorithm>
using namespace std;
#define NMAX 100005
#define INF 0x3f3f3f
FILE *in = fopen("arbint.in", "r");
FILE *out = fopen("arbint.out", "w");
int n, m;
int tree[NMAX * 4];
struct { int pos, val; } update;
struct { int begin, end; } query;
void runUpdate(int st, int dr, int posTree) {
if (st == dr) {
tree[posTree] = update.val;
return;
}
int mid = (st + dr) / 2;
if (update.pos <= mid)
runUpdate(st, mid, posTree * 2);
else
runUpdate(mid + 1, dr, posTree * 2 + 1);
tree[posTree] = max(tree[posTree * 2], tree[posTree * 2 + 1]);
}
int runQuery(int st, int dr, int posTree) {
if (query.begin <= st && dr <= query.end)
return tree[posTree];
if (query.end < st || dr < query.begin)
return 0;
int mid = (st + dr) / 2;
return max(runQuery(st, mid, posTree * 2), runQuery(mid + 1, dr, posTree * 2 + 1));
}
int main() {
fscanf(in, "%d %d", &n, &m);
for (int i = 1; i <= n; i++) {
fscanf(in, "%d ", &update.val);
update.pos = i;
runUpdate(1, n, 1);
}
for (int i = 1; i <= m; i++) {
static int tip;
fscanf(in, "%d ", &tip);
if (tip == 1) {
fscanf(in, "%d %d ", &update.pos, &update.val);
runUpdate(1, n, 1);
} else {
fscanf(in, "%d %d ", &query.begin, &query.end);
fprintf(out, "%d\n", runQuery(1, n, 1));
}
}
return 0;
}