#include <bits/stdc++.h>
using namespace std;
/**
Arbori de intervale
Se da a1, a2, ..., an
Operatii:
- 1 p x : a[p]=x
- 0 x y : care este valoarea maxima din a[x..y]
5 5
4 3 5 6 1
0 1 3
1 3 2
0 2 3
1 4 2
0 1 5
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
6 6 1 4 6 1 0 4 3 5 6 1 0 0 0
*/
int a[400005], n, N, m;
ifstream fin("arbint.in");
ofstream fout("arbint.out");
void Update(int p, int x)
{
int k;
a[p] = x;
while (p >= 1)
{
if (p % 2 == 1) p--;
k = p / 2; /// tata
a[k] = max(a[p], a[p + 1]);
p = k;
}
}
int Query(int p, int x, int y, int st, int dr)
{
int mid;
if (x == st && y == dr) return a[p];
else
{
mid = (st + dr) / 2;
if (y <= mid) /// [x,y] inclus in [st, mid]
return Query(2 * p, x, y, st, mid);
else if (mid + 1 <= x) /// [x,y] inclus in [mid+1,dr]
return Query(2 * p + 1, x, y, mid + 1, dr);
else /// x <= mid < y
return max(Query(2 * p, x, mid, st, mid),
Query(2 * p + 1, mid+1, y, mid + 1, dr));
}
}
int main()
{
int i, x, y, op;
fin >> n >> m;
N = 1;
while (N < n) N *= 2;
for (i = N; i < N + n; i++)
fin >> a[i];
for (i = N - 1; i >= 1; i--)
a[i] = max(a[2 * i], a[2 * i + 1]);
/// operatiile
for (i = 1; i <= m; i++)
{
fin >> op >> x >> y;
if (op == 0) fout << Query(1, x, y, 1, N) << "\n";
else Update(N + x - 1, y);
}
return 0;
}