#include <fstream>
using namespace std;
struct nod {
int max;
nod* stanga;
nod* dreapta;
};
nod* buildArbore(nod* root, int* v, int a, int b){
root = new nod;
if(b-a == 1){
root->stanga = buildArbore(root->stanga, v, a, a);
root->dreapta = buildArbore(root->dreapta, v, b, b);
}
else if (a != b) {
int m = (b+a)/2;
root->stanga = buildArbore(root->stanga, v, a, m);
root->dreapta = buildArbore(root->dreapta, v, m + 1, b);
}
if(a == b){
root->max = v[a];
root->stanga = NULL;
root->dreapta = NULL;
}
else
root->max = root->stanga->max > root->dreapta->max ? root->stanga->max : root->dreapta->max;
return root;
}
void rebuildArbore(nod* root, int idx, int newValue, int begin, int end){
if(!root->stanga && !root->dreapta){
root->max = newValue;
return ;
}
int m = (begin+end)/2;
if(idx <= m || idx == begin)
rebuildArbore(root->stanga, idx, newValue, begin, m);
else if(idx > m || idx == end)
rebuildArbore(root->dreapta, idx, newValue, m + 1, end);
root->max = root->stanga->max > root->dreapta->max ? root->stanga->max : root->dreapta->max;
}
int maxInt(nod* root, int a, int b, int currentMax, int begin, int end){
if(begin >= a && end <= b)
return root->max;
int maxSt = -1, maxDr = -1, m = (begin+end)/2;
if(a <= m)
maxSt = maxInt(root->stanga, a, m >= b ? b : m, currentMax, begin, m);
if(b > m)
maxDr = maxInt(root->dreapta, a >= m + 1 ? a : m + 1, b, currentMax, m+1, end);
return maxSt > maxDr ? maxSt : maxDr;
}
int main(){
ifstream fin("arbint.in");
ofstream fout("arbint.out");
fstream::sync_with_stdio(false);
int M,N;
fin>>N>>M;
int* v = new int[N];
for(int i = 0; i < N; i++)
fin>>v[i];
nod* root;
root = buildArbore(root, v, 0, N-1);
int op,a,b,max;
for(int i = 0; i < M; i++){
fin>>op>>a>>b;
if(!op)
fout<<maxInt(root, a-1, b-1, -1, 0, N-1)<<"\n";
else rebuildArbore(root, a-1, b, 0, N-1);
}
return 0;
}