#include <iostream>
#include <fstream>
#include <vector>
#include <bitset>
#include <string>
#include <algorithm>
#include <set>
#include <cassert>
#include <map>
#include <iomanip>
#include <functional>
#include <bits/stdc++.h>
using namespace std;
ifstream fin("arbint.in");
ofstream fout("arbint.out");
const bool LOCAL = true;
const bool DEBUG = LOCAL & false;
const bool HAS_TESTS = false;
template<typename T>
class SegmentTree{
private:
unsigned int size;
vector<T> segTree;
T identityElement;
function<T(T, T)> merge;
void computeChildren(int node, int left, int right, int& middle, int& leftChild, int& rightChild){
middle = (left + right) / 2;
leftChild = node + 1;
rightChild = leftChild + 2 * (middle - left + 1) - 1;
}
void build(int node, int left, int right, vector<T> v){
if(left == right){
segTree[node] = v[left];
}else{
int middle, leftChild, rightChild;
computeChildren(node, left, right, middle, leftChild, rightChild);
build(leftChild, left, middle, v);
build(rightChild, middle + 1, right, v);
segTree[node] = merge(segTree[leftChild], segTree[rightChild]);
}
}
void update(int node, int left, int right, int pos, T val){
if(left == right){
segTree[node] = val;
}else{
int middle, leftChild, rightChild;
computeChildren(node, left, right, middle, leftChild, rightChild);
if(pos <= middle)
update(leftChild, left, middle, pos, val);
else
update(rightChild, middle + 1, right, pos, val);
segTree[node] = merge(segTree[leftChild], segTree[rightChild]);
}
}
T query(int node, int left, int right, int qleft, int qright){
T retval = identityElement;
if(qleft <= left && right <= qright)
retval = segTree[node];
else{
int middle, leftChild, rightChild;
computeChildren(node, left, right, middle, leftChild, rightChild);
if(qleft <= middle)
retval = query(leftChild, left, middle, qleft, qright);
if(middle + 1 <= qright)
retval = merge(retval, query(rightChild, middle + 1, right, qleft, qright));
}
return retval;
}
public:
SegmentTree() : size(0), identityElement(T()), merge(nullptr){}
void resize(int _size){
size = _size;
segTree.resize(2 * size, identityElement);
}
void init(int _size, function<T(T, T)> _merge, T _identityElement, vector<T> v){
merge = _merge;
identityElement = _identityElement;
resize(_size);
build(0, 0, size - 1, v);
}
SegmentTree(int _size, function<T(T, T)> _merge, T _identityElement, vector<T> v){
init(_size, _merge, _identityElement, v);
}
void update(int pos, T val){
update(0, 0, size - 1, pos, val);
}
T query(int qleft, int qright){
return query(0, 0, size - 1, qleft, qright);
}
};
const int UPDATE = 1;
const int QUERY = 0;
int mx(int a, int b){
return (a > b) ? a : b;
}
void Solve(istream& in, ostream& out){
int n, m;
n = m = 5;
in >> n >> m;
vector<int> v(n);
for(auto& x: v)
in >> x;
SegmentTree<int> segtree(n, mx, -1, v);
int op, a, b;
for(int i = 0; i < m; ++i){
in >> op >> a >> b;
if(op == UPDATE)
segtree.update(a - 1, b);
else
out << segtree.query(a - 1, b - 1) << '\n';
}
}
signed main(){
if(LOCAL){
int tests;
if(HAS_TESTS)
fin >> tests;
else
tests = 1;
for(int test = 0; test < tests; ++test){
Solve(fin, fout);
}
}else{
int tests;
if(HAS_TESTS)
cin >> tests;
else
tests = 1;
for(int test = 0; test < tests; ++test){
Solve(cin, cout);
}
}
fin.close();
fout.close();
return 0;
}