#include<fstream>
#include<vector>
#include<iostream>
#include<cmath>
#define INF 100005
using namespace std;
ifstream fin("arbint.in");
ofstream fout("arbint.out");
vector<int> A;
int n, Q, a, b;
bool type;
vector<int> TREE;
void read() {
fin>>n>>Q;
int elem;
A.push_back(0);
TREE.resize(17*n, 0);
for(int i=1; i<=n; i++) {
fin>>elem;
A.push_back(elem);
}
}
void buildTree(int node, int cs, int cd) {
//cout<<"Am apelat buildTree("<<node<<", "<<cs<<", "<<cd<<").\n";
if(cs == cd) {
TREE[node] = A[cs];
return;
}
buildTree(node * 2, cs, (cs + cd)/2);
buildTree(node * 2 + 1, (cs + cd)/2 + 1, cd);
TREE[node] = max(TREE[node*2], TREE[node*2+1]);
}
int rmq (int &left, int &right, int node, int cs, int cd) {
if(cs > right || cd < left) return -1;
if(cs >= left && cd <= right) return TREE[node];
else
return max(
rmq(left, right, node*2, cs, (cs+cd)/2),
rmq(left, right, node*2+1, (cs+cd)/2+1, cd)
);
}
void updateTree (int poz, int val, int node, int cs, int cd) {
if(cs == cd) {
if(cs == poz)
TREE[node] = val;
return;
}
if((cs+cd)/2 >= poz)
updateTree (poz, val, node * 2, cs, (cs+cd)/2);
else
updateTree (poz, val, node * 2 + 1, (cs+cd)/2+1, cd);
TREE[node] = max(TREE[node*2], TREE[node*2+1]);
}
int main() {
read();
buildTree(1, 1, n);
A.empty();
//afisVect(TREE);
for(int i=0; i<Q; i++) {
fin>>type>>a>>b;
if(!type)
fout<<rmq(a, b, 1, 1, n)<<'\n';
else {
updateTree(a, b, 1, 1, n);
}
}
return 0;
}