#include <bits/stdc++.h>
#define VAL 1000000007
#define mp make_pair
using namespace std;
struct T
{
T *left, *right;
int key,pr,val,maxx;
T(int x, int xx)
{
key=x; val=maxx=xx; pr=rand()%VAL;
left=right=0;
}
} *root = 0;
inline int Maxx(T* nod)
{
if(!nod) return 0;
return nod->maxx;
}
inline void Upd(T* nod)
{
if(!nod) return;
nod->maxx=max(nod->val,max(Maxx(nod->left),Maxx(nod->right)));
}
inline T* Merge(T* L, T* R)
{
if(!L) return R;
if(!R) return L;
if(L->pr <= R->pr)
{
R->left=Merge(L,R->left);
Upd(R);
return R;
}
L->right=Merge(L->right,R);
Upd(L);
return L;
}
inline pair <T* , T*> Split(T* nod, int val)
{
if(!nod) return mp((T*) 0 , (T*) 0);
pair <T*,T*> spl;
if(nod->key > val)
{
spl=Split(nod->left,val);
nod->left=spl.second; spl.second=nod;
Upd(nod);
return spl;
}
else
{
spl=Split(nod->right,val);
nod->right=spl.first; spl.first=nod;
Upd(nod);
return spl;
}
}
inline T* Insert(int poz, int val)
{
return Merge(root,new T(poz,val));
}
inline void Update(int p, int val)
{
pair <T*,T*> spl=Split(root,p),spl1;
spl1=Split(spl.first,p-1);
spl1.second->val=spl1.second->maxx=val;
root=Merge(Merge(spl1.first,spl1.second),spl.second);
}
inline int Query(int st, int dr)
{
pair <T*,T*> spl=Split(root,st-1),spl1;
spl1=Split(spl.second,dr);
int sol=spl1.first->maxx;
root=Merge(spl.first,Merge(spl1.first,spl1.second));
return sol;
}
int main()
{
int x,m,poz,val,n,i,tip;
ifstream cin("arbint.in");
ofstream cout("arbint.out");
cin>>n>>m;
for(i=1;i<=n;++i)
{
cin>>x;
root = Insert(i,x);
}
while(m--)
{
cin>>tip>>poz>>val;
if(!tip) cout<<Query(poz,val)<<"\n";
else Update(poz,val);
}
return 0;
}