#include <bits/stdc++.h>
using namespace std;
vector<int> build_tree(vector<int> v, int n){
int len = 1 << (int)ceil(log2(n));
vector<int> seg (2 * len, INT_MIN);
int k = 1;
for(int i = len; (i <= 2 * len - 1) && (k <= n); ++i){
seg[i] = v[k++];
}
for(int i = len - 1; i >= 1; --i)
seg[i] = max(seg[2 * i], seg[2 * i + 1]);
return seg;
}
void update_tree(vector<int> &seg, int n, int pos, int val){
int len = 1 << (int)ceil(log2(n));
pos = len + pos - 1;
seg[pos] = val;
for(int k = pos / 2; k >= 1; k /= 2)
seg[k] = max(seg[2 * k], seg[2 * k + 1]);
}
int querry_tree(vector<int> seg, int n, int l, int r){
int len = 1 << (int)ceil(log2(n));
l += len - 1;
r += len - 1;
int m = INT_MIN;
while(l <= r){
if(l % 2 == 1)
m = max(m, seg[l++]);
if(r % 2 == 0)
m = max(m, seg[r--]);
l /= 2;
r /= 2;
}
return m;
}
ifstream in("arbint.in");
ofstream out("arbint.out");
#define cin in
#define cout out
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
int n, t, i, op;
vector<int> seg;
cin >> n >> t;
vector<int> v(n + 1);
for(i = 1 ; i <= n; ++i){
cin >> v[i];
}
seg = build_tree(v, n);
while (t--){
cin >> op;
if (op){
int pos, val;
cin >> pos >> val;
update_tree(seg, n, pos, val);
}
else{
int l, r;
cin >> l >> r;
cout << querry_tree(seg, n, l, r) << endl;
}
}
return 0;
}