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