#include <fstream>
using namespace std;
ifstream f ("arbint.in");
ofstream g ("arbint.out");
int const NM = 1e5;
int V [1 + NM] , aint [1 + 2 * NM] , n;
void build (int node , int from , int to){
int m = (from + to) / 2;
if (from < to){
build (node * 2 , from , m);
build (1 + node * 2 , m + 1 , to);
aint [node] = max (aint [2 * node] , aint [1 + 2 * node]);
}
if (from == to){
aint [node] = V [from];
}
return;
}
void update (int node , int from , int to , int pos , int val){
int m = (from + to) / 2;
if (from < to){
if (m >= pos)
update (node * 2 , from , m , pos , val);
else
update (1 + node * 2 , m + 1 , to , pos , val);
aint [node] = max (aint [node * 2] , aint [1 + node * 2]);
}
else
aint [node] = val;
}
int query (int node , int from , int to , int a , int b){
if (to < a || from > b)
return -1;
if(to <= b && from >= a)
return aint [node];
int m = (from + to) / 2;
return max (query (node * 2 , from , m , a , b) , query (node * 2 + 1 , m + 1 , to , a , b));
}
int main()
{
int m;
f >> n >> m;
for(int i = 1 ; i <= n ; ++ i)
f >> V [i];
build (1 , 1 , n);
for(int i = 1 ; i <= m ; ++ i){
int c , a , b;
f >> c >> a >> b;
if (! c)
g << query (1 , 1 , n , a , b) << '\n';
else
update (1 , 1 , n , a , b);
}
return 0;
}