// Infoarena - Arbori de intervale
#include <iostream>
#include <fstream>
const int MAX_N = 1e5 + 1;
int tree[4 * MAX_N];
int query(int node, int current_left, int current_right, int left, int right)
{
if (current_left >= left && current_right <= right) {
return tree[node];
}
int mid = (current_left + current_right) >> 1;
int ans = 0;
if (left <= mid) {
ans = std::max(ans, query(node * 2, current_left, mid, left, right));
}
if (right > mid) {
ans = std::max(ans, query(node * 2 + 1, mid + 1, current_right, left, right));
}
return ans;
}
void update(int node, int current_left, int current_right, int index, int value)
{
if (current_left == current_right) {
tree[node] = value;
return;
}
int mid = (current_left + current_right) >> 1;
if (index <= mid) {
update(node * 2 , current_left, mid, index, value);
} else {
update(node * 2 + 1, mid + 1, current_right, index, value);
}
tree[node] = std::max(tree[node * 2], tree[node * 2 + 1]);
}
int main()
{
std::ifstream fin("arbint.in");
std::ofstream fout("arbint.out");
int n, m;
fin >> n >> m;
for (int i = 0; i < n; ++i) {
int value;
fin >> value;
update(1, 0, n - 1, i, value);
}
while (m--) {
bool current_query;
int a, b;
fin >> current_query >> a >> b;
if (current_query == 0) {
fout << query(1, 0, n - 1, a - 1, b - 1) << '\n';
}
else if(current_query == 1) {
update(1, 0, n - 1, a - 1, b);
}
}
return 0;
}