#include <iostream>
#include <fstream>
#include <vector>
using namespace std;
vector<int> tree;
void update(int n, int l, int r, int pos, int val) {
if (l == r) {
tree[n] = val;
return;
}
int mid = (l + r) / 2;
if (pos <= mid) {
update(2 * n, l, mid, pos, val);
}
else {
update(2 * n + 1, mid + 1, r, pos, val);
}
tree[n] = max(tree[2LL * n], tree[2LL * n + 1]);
}
void query(int n, int l, int r, int start, int end, int &ans) {
if (start <= l && r <= end) {
ans = max(ans, tree[n]);
return;
}
int mid = (l + r) / 2;
if (start <= mid) {
query(2 * n, l, mid, start, end, ans);
}
if (mid < end) {
query(2 * n + 1, mid + 1, r, start, end, ans);
}
}
int main() {
ifstream fin("arbint.in");
ofstream fout("arbint.out");
int N;
int M;
fin >> N >> M;
tree.resize(4LL * N);
for (int i = 0; i < N; i++) {
int curr;
fin >> curr;
update(1, 1, N, i + 1, curr);
}
while (M--) {
short op;
int a;
int b;
int ans;
fin >> op >> a >> b;
switch (op) {
case 0:
ans = 0;
query(1, 1, N, a, b, ans);
fout << ans << "\n";
break;
case 1:
update(1, 1, N, a, b);
break;
}
}
return 0;
}