#include <fstream>
#include <iostream>
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) {
root->stanga = buildArbore(root->stanga, v, a, (b+a)/2);
root->dreapta = buildArbore(root->dreapta, v, (b+a)/2 + 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 ;
}
if(idx <= (begin+end)/2 || idx == begin)
rebuildArbore(root->stanga, idx, newValue, begin, (begin+end)/2);
else if(idx > (begin+end)/2 || idx == end)
rebuildArbore(root->dreapta, idx, newValue, (begin+end)/2 + 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;
if(a <= (begin+end)/2)
maxSt = maxInt(root->stanga, a, (begin+end)/2 >= b ? b : (begin+end)/2, currentMax, begin, (begin+end)/2);
if(b > (begin+end)/2)
maxDr = maxInt(root->dreapta, a >= (begin+end)/2 + 1 ? a : (begin+end)/2 + 1, b, currentMax, (begin+end)/2+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;
}