#include <fstream>
#include <algorithm>
using namespace std;
const string file_name = "arbint",
in_file_name = file_name + ".in",
out_file_name = file_name + ".out";
ifstream fin (in_file_name);
ofstream fout (out_file_name);
const int MAX = 1e5 + 5;
void build_tree(int arb_int[], int v[], int node, int left, int right) {
if (left == right) {
arb_int[node] = v[left];
return;
}
int left_son = 2 * node, right_son = 2 * node + 1, mid = (left + right) / 2;
build_tree(arb_int, v, left_son, left, mid);
build_tree(arb_int, v, right_son, mid + 1, right);
arb_int[node] = max(arb_int[left_son], arb_int[right_son]);
}
void update_tree(int arb_int[], int node, int left, int right, int pos, int val) {
if (left == right) {
arb_int[node] = val;
return;
}
int left_son = 2 * node, right_son = 2 * node + 1, mid = (left + right) / 2;
if (pos <= mid)
update_tree(arb_int, left_son, left, mid, pos, val);
else update_tree(arb_int, right_son, mid + 1, right, pos, val);
arb_int[node] = max(arb_int[left_son], arb_int[right_son]);
}
int get_max(int arb_int[], int node, int left, int right, int a, int b) {
if (left >= a && right <= b)
return arb_int[node];
int left_son = 2 * node, right_son = 2 * node + 1, mid = (left + right) / 2;
int sol = 0;
if (a <= mid)
sol = max(sol, get_max(arb_int, left_son, left, mid, a, b));
if (b > mid)
sol = max(sol, get_max(arb_int, right_son, mid + 1, right, a, b));
return sol;
}
int main() {
int length, queries;
int arb_int[4 * MAX], v[MAX];
fin >> length >> queries;
for (int i = 1; i <= length; i++)
fin >> v[i];
build_tree(arb_int, v, 1, 1, length);
for (int query, a, b; queries; queries--) {
fin >> query >> a >> b;
if (query)
update_tree(arb_int, 1, 1, length, a, b);
else fout << get_max(arb_int, 1, 1, length, a, b) << "\n";
}
return 0;
}