#include "bits/stdc++.h"
using namespace std;
#define fi first
#define se second
#define ll long long
#define dbg(v) cerr<<#v<<" = "<<v<<'\n'
#define vi vector<int>
#define vl vector <ll>
#define pii pair<int,int>
#define mp make_pair
#define db long double
#define pb push_back
#define all(s) s.begin(),s.end()
template < class T > T smin(T &a,T b) {if (a > b) a = b;return a;}
template < class T > T smax(T &a,T b) {if (a < b) a = b;return a;}
const int N = (int)(1e6) + 5;
class DSU
{
public:
int * f;
int * sz;
stack < pair < int* , int > > v;
public:
void init(int n)
{
f = new int[n + 5];
sz = new int[n + 5];
for (int i = 0;i < n + 5;++i)
f[i] = 0;
for (int i = 1;i <= n;++i)
f[i] = i,sz[i] = 1;
}
int get(int k)
{
return k == f[k] ? k : get(f[k]);
}
void go(int &a,int b)
{
v.push({&a,a});
return void(a = b);
}
void U(int a,int b)
{
a = get(a);b = get(b);
if (a == b) return;
if (sz[a] > sz[b])
swap(a,b);
go(f[a],b);
go(sz[b],sz[a] + sz[b]);
}
void Restore(int Size)
{
while (v.size() > Size)
{
*v.top().fi = v.top().se;
v.pop();
}
}
};
template < class T >
class Fenwick
{
public:
T * t;
function < T(T,T) > comb;
int n;
public:
void init(int N,T v,function < T(T,T) > cc)
{
n = N;
t = new T[n + 5];
for (int i = 0;i < n + 5;++i)
t[i] = v;
comb = cc;
}
T query(int i)
{
int ans = t[i];
for (i -= i&(-i);i;i -= i&(-i))
ans = comb(ans,t[i]);
return ans;
}
void update(int i,T v)
{
for (;i <= n;i += i&(-i))
t[i] = comb(t[i],v);
}
};
template < class T >
class segmenttree
{
public:
int nodes;
int *lf;
int *rg;
T * t;
int n;
T nil;
function < T(T,T) > comb;
function < void(int,int,int,T&,T&) > lz;
function < void(T&,T) > add;
public:
inline int get(int &K)
{
if (K == -1)
K = ++nodes,lf[K] = rg[K] = -1,t[K] = nil;
return K;
}
void init(int N,int SZ,T vv,function < T(T,T) > cc,function < void(T&,T) > ADD,function < void(int,int,int,T&,T&) > llz = [&](int a,int b,int c,T & d,T & e) {return;})
{
n = N;
lf = new int[SZ];
rg = new int[SZ];
t = new T[SZ];
lf[0] = rg[0] = -1;t[0] = vv;
nodes = 0;
nil = vv;
comb = cc;add = ADD;lz = llz;
}
void build(int l,int r,T a[],int node = 0)
{
if (l == r)
t[node] = a[l];
else
{
int m = (l + r) / 2;
build(l,m,a,get(lf[node]));
build(m+1,r,a,get(rg[node]));
t[node] = comb(t[lf[node]],t[rg[node]]);
}
}
void uu(int l,int r,int node)
{
if (l == r)
{
T s1,s2;
lz(l,r,node,s1,s2);
}
else
lz(l,r,node,t[get(lf[node])],t[get(rg[node])]);
}
T query(int l,int r,int l1,int r1,int node = 0)
{
uu(l,r,node);
if (l1 <= l && r <= r1)
return t[node];
else
{
int m = (l + r) / 2;
if (l1 <= m && m + 1 <= r1)
return comb(query(l,m,l1,r1,get(lf[node])),query(m+1,r,l1,r1,get(rg[node])));
else
if (l1 <= m)
return query(l,m,l1,r1,get(lf[node]));
else
return query(m+1,r,l1,r1,get(rg[node]));
}
}
void update(int l,int r,int l1,int r1,T v,int node = 0)
{
if (l1 <= l && r <= r1)
add(t[node],v);
else
{
int m = (l + r) / 2;
if (l1 <= m)
update(l,m,l1,r1,v,get(lf[node]));
else
uu(l,m,get(lf[node]));
if (m+1<=r1)
update(m+1,r,l1,r1,v,get(rg[node]));
else
uu(m+1,r,get(rg[node]));
t[node] = comb(t[lf[node]],t[rg[node]]);
}
uu(l,r,node);
}
};
int main(void)
{
freopen("arbint.in","r",stdin);
freopen("arbint.out","w",stdout);
int n,m;
scanf("%d%d",&n,&m);
segmenttree < int > tr;
tr.init(n,4 * n + 5,-1,[&](int a,int b){return max(a,b);},[&](int &a,int b) {a = b;});
vi s(n + 1);
for (int i = 1;i <= n;++i)
scanf("%d",&s[i]);
tr.build(1,n,s.data());
while (m --)
{
int op,l,r;
scanf("%d%d%d",&op,&l,&r);
if (!op)
printf("%d\n",tr.query(1,n,l,r));
else
tr.update(1,n,l,l,r);
}
return 0;
}