#include <cstdio>
#include <cstring>
#include <cassert>
#include <fstream>
#include <algorithm>
#include <vector>
#include <string>
#include <queue>
#include <map>
using namespace std;
typedef long long LL;
typedef vector<int>::iterator it;
const int oo = 0x3f3f3f3f;
const int MAX_N = 100005;
int N, Values[MAX_N], IT[4 * MAX_N], NQ;
void BuildIT(int X, int Left, int Right) {
int Middle = (Left + Right) / 2;
if (Left == Right) {
IT[X] = Values[Middle];
return;
}
BuildIT(2 * X, Left, Middle); BuildIT(2 * X + 1, Middle + 1, Right);
IT[X] = max(IT[2 * X], IT[2 * X + 1]);
}
void Update(int X, int Left, int Right, int Position, int Value) {
int Middle = (Left + Right) / 2;
if (Left == Right) {
IT[X] = Value;
return;
}
if (Position <= Middle)
Update(2 * X, Left, Middle, Position, Value);
else
Update(2 * X + 1, Middle + 1, Right, Position, Value);
IT[X] = max(IT[2 * X], IT[2 * X + 1]);
}
int Query(int X, int Left, int Right, int QLeft, int QRight) {
int Middle = (Left + Right) / 2;
if (QLeft <= Left && Right <= QRight)
return IT[X];
int Answer = -oo;
if (QLeft <= Middle)
Answer = max(Answer, Query(2 * X, Left, Middle, QLeft, QRight));
if (QRight > Middle)
Answer = max(Answer, Query(2 * X + 1, Middle + 1, Right, QLeft, QRight));
return Answer;
}
void Solve() {
BuildIT(1, 1, N);
assert(freopen("arbint.out", "w", stdout));
for (; NQ > 0; --NQ) {
int Type, X, Y; assert(scanf("%d %d %d", &Type, &X, &Y) == 3);
if (Type == 1)
Update(1, 1, N, X, Y);
else
printf("%d\n", Query(1, 1, N, X, Y));
}
}
void Read() {
assert(freopen("arbint.in", "r", stdin));
assert(scanf("%d %d", &N, &NQ) == 2);
for (int i = 1; i <= N; ++i)
assert(scanf("%d", &Values[i]) == 1);
}
int main() {
Read();
Solve();
return 0;
}