#include <cstdio>
#include <memory>
#include <vector>
#include <algorithm>
using namespace std;
class SegmentTree{
private:
vector<int> elem;
int arrSize;
void Build(typename vector<int>::iterator begin, typename vector<int>::iterator end, int pz) {
if (distance(begin, end) == 1) {
elem[pz] = *begin;
return;
}
int middleDist = distance(begin, end) / 2;
Build(begin, begin + middleDist, pz * 2 + 1);
Build(begin + middleDist, end, pz * 2 + 2);
elem[pz] = max(elem[pz * 2 + 1], elem[pz * 2 + 2]);
}
void Update(int begin, int end, int pz, int updatePos, int newValue) {
if (end - begin == 1) {
elem[pz] = newValue;
return;
}
int middleDist = (end - begin) / 2;
if (begin + middleDist > updatePos)
Update(begin, begin + middleDist, pz * 2 + 1, updatePos, newValue);
else
Update(begin + middleDist, end, pz * 2 + 2, updatePos, newValue);
elem[pz] = max(elem[pz * 2 + 1], elem[pz * 2 + 2]);
}
int QueryMax(int begin, int end, int pz, int left, int right) {
if (left <= begin && end <= right + 1) {
return elem[pz];
}
int middleDist = (end - begin) / 2;
int maxLeft = -1, maxRight = -1;
if (begin + middleDist > left)
maxLeft = QueryMax(begin, begin + middleDist, pz * 2 + 1, left, right);
if (right >= begin + middleDist)
maxRight = QueryMax(begin + middleDist, end, pz * 2 + 2, left, right);
return max(maxLeft, maxRight);
}
public:
SegmentTree(vector<int> arr) {
if (arr.empty())
return;
arrSize = (int)arr.size();
elem.resize(arrSize* 4);
Build(arr.begin(), arr.end(), 0);
}
void Update(int updatePos, int newValue) {
Update(0, arrSize, 0, updatePos, newValue);
}
int QueryMax(int left, int right) {
return QueryMax(0, arrSize, 0, left, right);
}
};
class Solver{
public:
Solver() {
freopen("arbint.in", "r", stdin);
freopen("arbint.out", "w", stdout);
}
~Solver() {
fclose(stdin);
fclose(stdout);
}
void solve() {
int N, M;
scanf("%d%d", &N, &M);
vector<int> v(N);
for (int i = 0; i < N; ++i)
scanf("%d", &v[i]);
SegmentTree tree(v);
int a, b, op;
for (int i = 0; i < M; ++i) {
scanf("%d%d%d", &op, &a, &b);
if (op == 1)
tree.Update(a - 1, b);
else
printf("%d\n", tree.QueryMax(a - 1, b - 1));
}
}
};
int main() {
unique_ptr<Solver> s = make_unique<Solver>();
s->solve();
return 0;
}