#include <fstream>
#include <algorithm>
#include <iomanip>
#include <numeric>
#include <bitset>
#include <string>
#include <vector>
#include <cmath>
#include <queue>
#include <deque>
#include <stack>
#include <map>
#include <set>
#define int long long
//#define int short
#define f first
#define s second
using namespace std;
ifstream cin("arbint.in");
ofstream cout("arbint.out");
int n, q, tree[400005];
void build(const vector<int> &a, int node, int l, int r){
if (l == r){
tree[node] = a[l];
return;
}
int mid = (l + r) / 2;
build(a, 2 * node, l, mid);
build(a, 2 * node + 1, mid + 1, r);
tree[node] = max(tree[2 * node], tree[2 * node + 1]);
}
void update(int node, int l, int r, int pos, int val){
if (l == r){
tree[node] = val;
return;
}
int mid = (l + r) / 2;
if (pos <= mid){
update(2 * node, l, mid, pos, val);
}
else{
update(2 * node + 1, mid + 1, r, pos, val);
}
tree[node] = max(tree[2 * node], tree[2 * node + 1]);
}
int query(int node, int l, int r, int ql, int qr){
if (qr < l || ql > r){
return 0;
}
if (ql <= l && qr >= r){
return tree[node];
}
int mid = (l + r) / 2;
return max(query(2 * node, l, mid, ql, qr), query(2 * node + 1, mid + 1, r, ql, qr));
}
signed main(){
cin>>n>>q;
vector<int> v(n + 1);
for (int i = 1; i <= n; i++){
cin>>v[i];
}
build(v, 1, 1, n);
while (q--){
int c, a, b;
cin>>c>>a>>b;
if (c == 1){
update(1, 1, n, a, b);
}
else{
cout<<query(1, 1, n, a, b)<<"\n";
}
}
}