#include <iostream>
#include <fstream>
#include <vector>
using namespace std;
vector<int> tree;
//vector<int> lazy;
int N, M, c, a, b, x;
void update_pos(int node, int st, int dr, int pos, int x);
int query(int node, int st, int dr, int a, int b);
//void update_interval(int node, int st, int dr, int a, int b, int x);
//void propagate(int node, int st, int dr);
int main()
{
freopen("arbint.in", "rt", stdin);
freopen("arbint.out", "wt", stdout);
scanf("%d%d", &N, &M);
tree.assign(4*N, 0);
for(int i=1; i<=N; ++i) {
scanf("%d", &x);
update_pos(1, 1, N, i, x);
}
for(int i=1; i<=M; ++i) {
scanf("%d%d%d", &c, &a, &b);
if(c == 1)
update_pos(1, 1, N, a, b);
else
cout<<query(1, 1, N, a, b)<<'\n';
}
return 0;
}
/*void update_interval(int node, int st, int dr, int a, int b, int x)
{
if(a <= st && b >= dr) {
tree[node] += (dr - st + 1) * x;
lazy[node] += x;
return;
}
propagate(node, st, dr);
int mij = (dr - st)/2;
if(a <= mij)
update_interval(node * 2, st, mij, a, b, x);
if(b >= mij)
update_interval(node * 2 + 1, mij + 1, dr, a, b, x);
}
void propagate(int node, int st, int dr)
{
int mij = (dr - st)/2 + dr;
tree[node * 2] += (mij - st) * lazy[node];
tree[node * 2 + 1] += (dr - mij) * lazy[node];
lazy[node * 2] += lazy[node];
lazy[node * 2 + 1] += lazy[node];
lazy[node] = 0;
}*/
int query(int node, int st, int dr, int a, int b)
{
int ans = -1;
if( ( a <= st && dr <= b ) || st == dr)
return tree[node];
int mij = (dr - st)/2 + st;
if(a <= mij)
ans = max(ans, query(node * 2, st, mij, a, b) );
if(b > mij)
ans = max(ans, query(node * 2 + 1, mij+1, dr, a, b) );
return ans;
}
void update_pos(int node, int st, int dr, int pos, int x)
{
if(st == dr) {
tree[node] = x;
return;
}
int mij = (dr - st)/2 + st;
if(pos <= mij)
update_pos(node * 2, st, mij, pos, x);
else
update_pos(node * 2 + 1, mij+1, dr, pos, x);
tree[node] = max(tree[node * 2], tree[node * 2 + 1]);
}