// ARBORI DE INTERVALE
#include <fstream>
#define DIM 100001
using namespace std;
ifstream cin("arbint.in");
ofstream cout("arbint.out");
int v[DIM], tree[4*DIM], n, m;
void build(int node, int left, int right) {
if (left == right) {
tree[node] = v[left];
return;
}
int mid = (left + right) / 2;
build(2 * node, left, mid);
build(2 * node + 1, mid + 1, right);
tree[node] = max(tree[2 * node], tree[2 * node + 1]);
}
void update(int node, int left, int right, int pos, int val) {
if (left == right) {
tree[node] = val;
return;
}
int mid = (left + right) / 2;
if (pos <= mid)
update(2 * node, left, mid, pos, val);
else
update(2 * node + 1, mid + 1, right, pos, val);
tree[node] = max(tree[2 * node], tree[2 * node + 1]);
}
int query(int node, int left, int right, int x, int y) {
if (x <= left && y >= right)
return tree[node];
int mid = (left + right) / 2;
int ans1 = 0, ans2 = 0;
if (x <= mid)
ans1 = query(2 * node, left, mid, x, y);
if (y >= mid + 1)
ans2 = query(2 * node + 1, mid + 1, right, x, y);
return max(ans1, ans2);
}
int main() {
cin >> n >> m;
for (int i = 1; i <= n; ++i)
cin >> v[i];
build(1, 1, n);
for (int i = 1, a, b, x, y, op; i <= m; ++i) {
cin >> op;
if (op == 0)
cin >> x >> y, cout << query(1, 1, n, x, y) << "\n";
else if (op == 1)
cin >> a >> b, update(1, 1, n, a, b);
}
return 0;
}