#include <iostream>
#include <fstream>
#include <cstring>
#include <algorithm>
#include <deque>
#include <iomanip>
#include <queue>
#include <cmath>
#include <map>
#include <vector>
#include <bitset>
#include <unordered_map>
#include <set>
using namespace std;
ifstream fin("arbint.in");
ofstream fout("arbint.out");
int n, m;
map<pair<int, int>, pair<int, int>> parents;
map<pair<int, int>, vector<pair<int, int>>> graph;
map<pair<int, int>, int> cost;
void findParents(int left, int right) {
if (left == right) {
return;
}
parents[{left, (left + right) / 2}] = {left, right};
parents[{(left + right) / 2 + 1, right}] = {left, right};
graph[{left, right}].push_back({left, (left + right) / 2});
graph[{left, right}].push_back({(left + right) / 2 + 1, right});
findParents(left, (left + right) / 2);
findParents((left + right) / 2 + 1, right);
}
void update(pair<int, int> currentNode) {
while (currentNode.first && currentNode.second) {
cost[currentNode] = max(cost[graph[currentNode].front()], cost[graph[currentNode].back()]);
currentNode = parents[currentNode];
}
}
void modifyPos(int left, int right, int number) {
cost[{left, right}] = number;
}
int findMax(int left, int right, int a, int b) {
if (a <= left && right <= b) {
return cost[{left, right}];
} else if (right < a || left > b) {
return 0;
}
return max(findMax(left, (left + right) / 2, a, b), findMax((left + right) / 2 + 1, right, a, b));
}
int main() {
fin >> n >> m;
findParents(1, n);
for (int i = 1; i <= n; ++i) {
int number;
fin >> number;
modifyPos(i, i, number);
update(parents[{i, i}]);
}
for (int i = 1; i <= m; ++i) {
int op, a, b;
fin >> op >> a >> b;
if (op == 0) {
fout << findMax(1, n, a, b) << '\n';
} else {
modifyPos(a, a, b);
update(parents[{a, a}]);
}
}
return 0;
}