#include <iostream>
#include <fstream>
#define MAX 100001
using namespace std;
ifstream fin("arbint.in");
ofstream fout("arbint.out");
unsigned A[MAX], tree[4 * MAX];
void build(
unsigned node,
unsigned st,
unsigned dr
) {
if (st == dr) {
tree[node] = A[st];
return;
}
unsigned mid = (st + dr) / 2;
build(2 * node, st, mid);
build(2 * node + 1, mid + 1, dr);
tree[node] = max(tree[2 * node], tree[2 * node + 1]);
}
void update(
unsigned node,
unsigned st,
unsigned dr,
unsigned p,
unsigned v
) {
if (st == dr) {
tree[node] = v;
return;
}
unsigned mid = (st + dr) / 2;
if (p <= mid)
update(2 * node, st, mid, p, v);
else
update(2 * node + 1, mid + 1, dr, p, v);
tree[node] = max(tree[2 * node], tree[2 * node + 1]);
}
unsigned query(
unsigned node,
unsigned st,
unsigned dr,
unsigned a,
unsigned b
) {
if (b < st || dr < a)
return 0;
if (a <= st && dr <= b)
return tree[node];
unsigned mid = (st + dr) / 2;
return max(query(2 * node, st, mid, a, b),
query(2 * node + 1, mid + 1, dr, a, b));
}
int main() {
unsigned N, M;
fin >> N >> M;
for (unsigned i = 1; i <= N; ++i)
fin >> A[i];
build(1, 1, N);
unsigned T, a, b;
while (M--) {
fin >> T >> a >> b;
switch (T) {
case 0:
fout << query(1, 1, N, a, b) << '\n';
break;
default:
update(1, 1, N, a, b);
break;
}
}
}