#include <stdio.h>
#include <vector>
//#include <iostream>
using namespace std;
// T must have the = and < operators
template <class T>
class ArboreInterval
{
vector<T> Elem;
int Size;
void _Init(int tree_index, int l, int r)
{
if (Elem.size() <= tree_index) Elem.resize(tree_index+1);
if (l != r)
{
_Init(tree_index*2, l, (l+r)/2 );
_Init(tree_index*2 + 1, (l+r)/2 + 1, r);
}
}
int _modify_index; T _modify_newVal;
void _Modify (int index, int l, int r)
{
if (l != r)
{
int m = l+(r-l)/2;
if (_modify_index > m) _Modify (2*index + 1, m+1, r);
else _Modify (2*index, l, m);
Elem[index] = (Elem[2*index] < Elem[2*index + 1]) ? Elem[2*index + 1] : Elem[2*index] ;
}
else {
Elem[index] = _modify_newVal;
}
}
T _Max (int index, int sl, int sr, int l, int r)
{
if ((sl == l && sr == r) || l==r) return Elem[index];
int ml = max(sl, l);
int mr = min(sr, r);
int mid = l + (r-l)/2;
// Go only left
if (mr <= mid) return _Max(2*index, ml, mr, l, mid);
// Only right
else if (ml > mid) return _Max(2*index + 1, ml, mr, mid+1, r);
// Both
else {
T a = _Max(2*index, ml, mr, l, mid);
T b = _Max(2*index + 1, ml, mr, mid+1, r);
return (a<b) ? b : a;
};
}
public:
ArboreInterval() { }
ArboreInterval(int size) { Initialize(size); }
void Initialize(int size)
{
Size = size;
_Init(1,1,size);
}
void ModifyValue (int index, T newVal)
{
_modify_index = index; _modify_newVal = newVal;
_Modify(1,1,Size);
}
T GetMax (int left, int right)
{
return _Max(1, left, right, 1, Size);
}
/*void __Display()
{
cout<<"Items: ";
for (int i=1; i<Elem.size(); i++)
cout<<Elem[i]<<" ";
}*/
};
int main()
{
freopen ("arbint.in", "r", stdin);
freopen ("arbint.out", "w", stdout);
ArboreInterval<int> arb;
int N, M, x, y, op;
scanf("%d %d", &N, &M);
arb.Initialize(N);
for (int i=1; i<=N; i++)
{
scanf("%d", &x); arb.ModifyValue(i,x);
}
for (; M>0; M--)
{
scanf("%d %d %d", &op, &x, &y);
if (op == 0) printf("%d\n", arb.GetMax(x,y));
else arb.ModifyValue(x,y);
}
return 0;
}