///INTERVAL TREE
#include <iostream>
#include <fstream>
#include <vector>
using namespace std;
void update(vector<int>& intTree, int tInd,
const int vInd, const int val, int x, int y) {
if(x==y) {
intTree[tInd] = val;
return;
}
int m = (x+y)/2;
if(vInd+1 <= m) {
if(x<=m)
update(intTree, 2*tInd, vInd, val, x, m);
} else
if(m+1<=y)
update(intTree, 2*tInd+1, vInd, val, m+1, y);
intTree[tInd] = max(intTree[2*tInd], intTree[2*tInd+1]);
}
int query(vector<int>& intTree, int tInd, const int a, const int b, int x, int y) {
if(a<=x && y<=b) {
return intTree[tInd];
}
int m = (x+y)/2;
int right, left;
left = right = 0;
if(a <= m && x<=m)
left = query(intTree, 2*tInd, a, b, x, m);
if(b > m && m+1<=y)
right = query(intTree, 2*tInd+1, a, b, m+1, y);
return max(left, right);
}
int main() {
ifstream inStr("arbint.in");
ofstream outStr("arbint.out");
int N, M;
inStr >> N >> M;
vector<int> data(N);
vector<int> intTree(2*N+10, 0);
for(int i=0; i<N; ++i) {
inStr >> data[i];
update(intTree, 1, i, data[i], 1, N);
}
int tp, a, b;
for(int i=0; i<M; ++i) {
inStr >> tp >> a >> b;
if(!tp) outStr << query(intTree, 1, a, b, 1, N) << '\n';
else update(intTree, 1, a-1, b, 1, N);
}
return 0;
}