#include <bits/stdc++.h>
using namespace std;
ifstream in("arbint.in");
ofstream out("arbint.out");
int const NMAX = 1e5;
int n, m;
int seg[1 + 4 * NMAX];
int query(int node, int left, int right, int from, int to) {
int mid = (left + right) / 2;
if(left == from && right == to) {
return seg[node];
} else if(left <= from && to <= mid) {
return query(2*node, left, mid, from, to);
} else if(mid+1 <= from && to <= right) {
return query(2*node + 1, mid+1, right, from, to);
} else {
int m1 = query(2*node, left, mid, from, mid);
int m2 = query(2*node + 1, mid+1, right, mid+1, to);
return max(m1, m2);
}
}
//left-right is an intervals of indices left, left+1, .. right.
//node is node ID
//left-right is a segment of array indices
void update(int node, int left, int right, int pos, int value) {
int mid = (left + right) / 2;
if(left == right) {
seg[node] = value;
assert(left == pos);
} else {
if(left <= pos && pos <= mid) {
update(2*node, left, mid, pos, value);
} else {
update(2*node + 1, mid+1, right, pos, value);
}
seg[node] = max(seg[2*node], seg[2*node + 1]);
}
}
int main() {
in >> n >> m;
for(int i = 1; i <= n; i++) {
int x;
in >> x;
update(1, 1, n, i, x);
}
for(int i = 1; i <= m; i++) {
int type;
int start, end;
in >> type >> start >> end;
if(type == 0) {
out << query(1, 1, n, start, end) << "\n";
} else {
update(1, 1, n, start, end);
}
}
return 0;
}