#include <iostream>
#include <cstdio>
#include <fstream>
using namespace std;
ifstream fin("arbint.in");
ofstream fout("arbint.out");
const int N = 100000;
const int INF = 1e9;
struct node{
int val;
} arb[2*N - 1];
int v[N];
void uniteNodes(int parent, int left_son, int right_son){
arb[parent].val = max(arb[left_son].val, arb[right_son].val);
}
int uniteValues(int left_value, int right_value){
return max(left_value, right_value);
}
void build(int node, int left, int right){
if(left == right){
arb[node].val = v[left];
return;
}
int mij = (left + right)/2;
build(2*node, left, mij);
build(2*node + 1, mij + 1, right);
uniteNodes(node, 2*node, 2*node + 1);
}
int query(int node, int left, int right, int L, int R){
if(left > R || right < L)
return -INF;
if(L <= left && right <= R)
return arb[node].val;
int mij = (left + right)/2;
int left_value = query(2*node, left, mij, L, R);
int right_value = query(2*node + 1, mij + 1, right, L ,R);
return uniteValues(left_value, right_value);
}
void update(int node, int left, int right, int index, int val){
if(left == right){
v[index] = val;
arb[node].val = val;
return;
}
int mij = (left + right)/2;
if(index <= mij)
update(2*node, left, mij, index, val);
else
update(2*node + 1, mij + 1, right, index, val);
uniteNodes(node, 2*node, 2*node + 1);
}
int main()
{
int n,m,i,op,a,b;
fin >> n >> m;
for(i=1; i<=n; i++)
fin >> v[i];
build(1, 1, n);
for(i=0; i<m; i++){
fin >> op >> a >> b;
if(op == 0)
fout << query(1, 1, n, a, b) <<"\n";
else
update(1, 1, n, a, b);
}
return 0;
}