#include <fstream>
using namespace std;
const int NMAX = 100000;
int ArbInt[4 * NMAX];
int v[NMAX];
int n, m;
int build (int nod, int st, int dr)
{
if (dr - st < 1)
{
ArbInt[nod] = v[st];
return v[st];
}
int mid = (st + dr) / 2;
int vl = build (nod * 2 + 1, st, mid);
int vr = build (nod * 2 + 2, mid + 1, dr);
ArbInt[nod] = max (vl, vr);
return ArbInt[nod];
}
bool intersect (int x1, int y1, int x2, int y2)
{
return x2 <= y1 && x1 <= y2;
}
bool suprapun (int x1, int y1, int x2, int y2)
{
return x2 <= y1 && x1 >= x2 && y2 >= y1;
}
int query(int nod, int st, int dr, int a, int b)
{
if (suprapun (st, dr, a, b))
return ArbInt[nod];
int mid = (st + dr) >> 1;
int p1 = 0, p2 = 0;
if (intersect(a, b, st, mid))
p1 = query (nod * 2 + 1, st, mid, a, b);
if (intersect(a, b, mid + 1, dr))
p2 = query (nod * 2 + 2, mid + 1, dr, a, b);
return max(p1, p2);
}
int update (int nod, int st, int dr, int a, int b, int val)
{
if (suprapun(st, dr, a, b))
{
ArbInt[nod] = val;
return val;
}
int mid = (st + dr) >> 1;
int p1 = 0, p2 = 0;
if (intersect(st, mid, a, b))
p1 = update(nod * 2 + 1, st, mid, a, b, val);
if (intersect(mid + 1, dr, a,b))
p2 = update(nod * 2 + 2, mid + 1, dr, a, b, val);
ArbInt[nod] = max(ArbInt[nod * 2 + 1], ArbInt[nod * 2 + 2]);
}
void createArbInt()
{
build(0, 0, n - 1);
}
int main()
{
ifstream in("arbint.in");
ofstream out("arbint.out");
in >> n >> m;
for (int i = 0; i < n; ++i)
in >> v[i];
createArbInt();
for (int i = 0; i < m; ++i)
{
int t, x, y;
in >> t >> x >> y;
if (t == 0)
out << query(0, 0, n - 1, x - 1, y - 1) << "\n";
if (t == 1)
update(0, 0, n - 1, x - 1, x - 1, y);
}
return 0;
}