//Code by Patcas Csaba
//Time complexity:
//Space complexity:
//Method:
//Working time: 19:31
#include <stdio.h>
#include <ctype.h>
#include <vector>
#include <string>
#include <set>
#include <map>
#include <iostream>
#include <sstream>
#include <numeric>
#include <algorithm>
#include <cmath>
#include <queue>
#include <bitset>
#include <time.h>
#include <assert.h>
using namespace std;
#define in_file "arbint.in"
#define out_file "arbint.out"
#define VI vector <int>
#define FORN(i,n) for(int i=0;i<n;++i)
#define FOR(i,a,b) for(int i=a;i<=b;++i)
#define S size()
#define B begin()
#define E end()
#define X first
#define RS resize
#define Y second
#define PB push_back
#define MP make_pair
#define ALL(x) x.begin(),x.end()
#define repeat do{
#define until(x) }while(!(x));
#define left node<<1
#define right node<<1|1
int n, m;
VI a, ai;
int query(int node, int down, int up, int d, int u)
{
if (d<=down && up<=u) return ai[node];
int mid= (down + up) / 2, ans=0;
if (d<=mid) ans=query(left,down,mid,d,u);
if ((mid+1)<=u) ans=max(ans,query(right,mid+1,up,d,u));
return ans;
}
void update(int node, int down, int up, int ind, int val)
{
if (down==up)
{
ai[node]=val;
return ;
}
int mid= (down + up) / 2, ans=0;
if (ind<=mid) update(left,down,mid,ind,val);
else update(right,mid+1,up,ind,val);
ai[node]=max(ai[left],ai[right]);
}
int build(int node, int down, int up)
{
if (down==up)
{
ai[node]=a[down];
return a[down];
}
int mid= (down + up) / 2, ans;
ans=build(left,down,mid);
ans=max(ans,build(right,mid+1,up));
ai[node]=ans;
return ans;
}
int main()
{
FILE* fin=fopen(in_file,"r");
FILE* fout=fopen(out_file,"w");
fscanf(fin,"%d%d",&n,&m);
int pow2=1;
while (pow2<=n) pow2<<=1;
ai.RS((pow2<<1)+1);
a.RS(n+1);
FOR(i,1,n) fscanf(fin,"%d",&a[i]);
build(1,1,n);
FORN(i,m)
{
int x, y, z;
fscanf(fin,"%d%d%d",&x,&y,&z);
if (x==0)
fprintf(fout,"%d\n",query(1,1,n,y,z));
else update(1,1,n,y,z);
}
fclose(fin);
fclose(fout);
return 0;
}