#include <iostream>
#include <fstream>
using namespace std;
ifstream f("arbint.in");
ofstream g("arbint.out");
const int NMAX = 1e5 + 1;
int v[NMAX];
int n, q;
struct segment_tree
{
int T[4 * NMAX];
void build(int node, int st, int dr)
{
if (st == dr)
{
T[node] = v[st];
return;
}
int mij = (st + dr) / 2;
build(2 * node, st, mij);
build(2 * node + 1, mij + 1, dr);
T[node] = max(T[2 * node], T[2 * node + 1]);
}
void update(int node, int st, int dr, int poz, int val)
{
if (st == dr)
{
T[node] = val;
return;
}
int mij = (st + dr) / 2;
if (poz <= mij)
update(2 * node, st, mij, poz, val);
else
update(2 * node + 1, mij + 1, dr, poz, val);
T[node] = max(T[2 * node], T[2 * node + 1]);
}
int query(int node, int st, int dr, int l, int r)
{
if (node < 0)
return 0;
if (l > r)
return 0;
if ((st == l) && (dr == r))
return T[node];
int mij = (st + dr) / 2;
int node1 = query(2 * node, st, mij, l, min(mij, r)),
node2 = query(2 * node + 1, mij + 1, dr, max(mij + 1, l), r);
return max(node1, node2);
}
} AINT;
void read_vec()
{
f >> n >> q;
for (int i = 1; i <= n; i++)
f >> v[i];
}
void solve_queries()
{
for (int i = 1; i <= q; i++)
{
int tip, a, b;
f >> tip >> a >> b;
if (tip == 0)
g << AINT.query(1, 1, n, a, b) << '\n';
else
AINT.update(1, 1, n, a, b);
}
}
int main()
{
read_vec();
AINT.build(1, 1, n);
solve_queries();
return 0;
}