#include <iostream>
#include <fstream>
#include <vector>
using namespace std;
ifstream fin("arbint.in");
ofstream fout("arbint.out");
struct St
{
int l, r, x;
St *ltree, *rtree;
St(int l, int r, int x, St *ltree, St *rtree)
: l(l), r(r), x(x), ltree(ltree), rtree(rtree) {}
};
St* build(const vector<int>& v, int l, int r)
{
St *ltree = nullptr, *rtree = nullptr;
int x, m = (l + r) / 2;
if(l == r)
x = v[m];
else
{
ltree = build(v, l, m);
rtree = build(v, m + 1, r);
x = max(ltree->x, rtree->x);
}
return new St(l, r, x, ltree, rtree);
}
int query(St *root, int l, int r)
{
if(root->l == l && root->r == r)
return root->x;
else if(r <= root->ltree->r)
return query(root->ltree, l, r);
else if(l >= root->rtree->l)
return query(root->rtree, l, r);
else
{
int lx = query(root->ltree, l, root->ltree->r);
int rx = query(root->rtree, root->rtree->l, r);
return max(lx, rx);
}
}
void update(St *root, int p, int k)
{
if(root->ltree == nullptr && root->rtree == nullptr)
root->x = k;
if(root->ltree)
if(p <= root->ltree->r)
update(root->ltree, p, k);
if(root->rtree)
if(p >= root->rtree->l)
update(root->rtree, p, k);
if(root->ltree && root->rtree)
root->x = max(root->ltree->x, root->rtree->x);
}
int main()
{
int n, q;
fin >> n >> q;
vector<int> v(n + 1);
for(int i = 1; i <= n; i++)
fin >> v[i];
St *root = build(v, 1, n);
for(int i = 1; i <= q; i++)
{
int t, a, b;
fin >> t >> a >> b;
if(t == 0) // Interogare
fout << query(root, a, b) << '\n';
else
update(root, a, b);
}
fin.close();
fout.close();
return 0;
}