// g++ meditatii.cpp -o main & ./main
#include <bits/stdc++.h>
using namespace std;
vector<int> v;
vector<int> tree;
void init(int node, int left, int right){
if (left == right){
// leaf
tree[node] = v[left];
return;
}
int mid = (left + right) / 2;
// left subtree
init(node * 2, left , mid);
// right subtree
init(node * 2 + 1, mid + 1, right);
// combine
tree[node] = max(tree[node * 2], tree[node * 2 + 1]);
}
void update(int node, int left, int right, int pos, int val){
if (left == right){
// leaf
v[pos] = val; // useful only if you need v
tree[node] = val;
return;
}
int mid = (left + right) / 2;
if (pos <= mid){
update(node * 2, left, mid, pos, val);
}
else{
update(node * 2 + 1, mid + 1, right, pos, val);
}
// combine
tree[node] = max(tree[node * 2], tree[node * 2 + 1]);
}
int query(int node, int left, int right, int a, int b){
if (a <= left && right <= b){
return tree[node];
}
int mid = (left + right) / 2;
int ret = 0; // smallest value possible since the numbers are natural
if (a <= mid){
ret = max(ret, query(node * 2, left, mid, a, b));
}
if (mid + 1 <= b){
ret = max(ret, query(node * 2 + 1, mid + 1, right, a, b));
}
return ret;
}
int main() {
// freopen("input.txt", "r", stdin); freopen("output.txt", "w", stdout);
freopen("arbint.in", "r", stdin); freopen("arbint.out", "w", stdout);
int n, m;
cin>>n>>m;
v.resize(n+1);
for (int i=1; i<=n; i++){
cin>>v[i];
}
// initializare
tree.resize(4*n);
init(1, 1, n);
for (int i=1; i<=m; i++){
int t, a, b;
cin>>t>>a>>b;
if (t == 0){
cout<<query(1, 1, n, a, b)<<'\n';
}
else{
update(1, 1, n, a, b);
}
}
return 0;
}