#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
class ArbInt{
public:
void Build(vector<int> *v) {
range_.resize(4 * (int)v->size());
size_ = v->size();
Build_(0, size_ - 1, 0, v);
}
void Update(int pos, int val) {
Update_(0, size_ - 1, 0, pos, val);
}
int Query(int left, int right) {
return Query_(0, size_ - 1, 0, left, right);
}
private:
int Query_(int li, int lf, int pz, int left, int right) {
if (left <= li && lf <= right)
return range_[pz];
int m = li + (lf - li) / 2;
int maxLeft = -(1<<30);
int maxRight = -(1<<30);
if (m >= left)
maxLeft = Query_(li, m, pz*2 + 1, left, right);
if (right > m)
maxRight = Query_(m + 1, lf, pz*2 + 2, left, right);
return max(maxLeft, maxRight);
}
void Update_(int li, int lf, int pz, int pos, int val) {
if (li == lf) {
range_[pz] = val;
return;
}
int m = li + (lf - li) / 2;
if (pos <= m)
Update_(li, m, 2*pz + 1, pos, val);
else
Update_(m + 1, lf, 2*pz + 2, pos, val);
range_[pz] = max(range_[2*pz + 1], range_[2*pz + 2]);
}
void Build_(int li, int lf, int pz, vector<int> *v) {
if (li == lf) {
range_[pz] = (*v)[li];
return;
}
int m = li + (lf - li) / 2;
Build_(li, m, 2*pz + 1, v);
Build_(m + 1, lf, 2*pz + 2, v);
range_[pz] = max(range_[2*pz + 1], range_[2*pz + 2]);
}
vector<int> range_;
int size_;
};
int main()
{
freopen("arbint.in", "r", stdin);
freopen("arbint.out", "w", stdout);
int N, M;
scanf("%d%d", &N, &M);
vector<int> v(N);
for (int i = 0; i < N; ++i)
scanf("%d", &v[i]);
ArbInt arbInt;
arbInt.Build(&v);
for (int i = 0; i < M; ++i) {
int op, a, b;
scanf("%d%d%d", &op, &a, &b);
if (op == 1)
arbInt.Update(a - 1, b);
else
printf("%d\n", arbInt.Query(a - 1, b - 1));
}
return 0;
}