#include <bits/stdc++.h>
using namespace std;
inline void Boost() {
ios::sync_with_stdio(false);
cin.tie(NULL); cout.tie(NULL);
}
typedef long long int ll;
typedef long double ld;
ifstream fin("arbint.in");
ofstream fout("arbint.out");
template < typename T >
class SegmentTree {
int dim;
vector < T > data;
void build(const int &node, const int &lo, const int &hi, const vector < T > &from) {
if(lo + 1 == hi) {
data[node] = from[lo];
} else {
int mid = (lo + hi) / 2;
build(node * 2, lo, mid, from);
build(node * 2 + 1, mid, hi, from);
data[node] = max(data[node * 2], data[node * 2 + 1]);
}
}
void update(const int &node, const int &lo, const int &hi, const int &pos, const T &val) {
if(lo + 1 == hi) {
data[node] = val;
} else {
int mid = (lo + hi) / 2;
if(pos < mid) {
update(node * 2, lo, mid, pos, val);
} else {
update(node * 2 + 1, mid, hi, pos, val);
}
data[node] = max(data[node * 2], data[node * 2 + 1]);
}
}
void query(const int &node, const int &lo, const int &hi, const int &x, const int &y) {
if(lo >= x && hi <= y) {
if(lo == x) {
data[0] = data[node];
} else {
data[0] = max(data[0], data[node]);
}
} else {
int mid = (lo + hi) / 2;
if(x < mid) query(node * 2, lo, mid, x, y);
if(y > mid) query(node * 2 + 1, mid, hi, x, y);
}
}
public:
SegmentTree(const int &dim) : dim(dim), data(dim * 4) {}
void MakeTree(const vector < T > &from) {
build(1, 0, dim, from);
}
void Set(const int &pos, const T &val) {
update(1, 0, dim, pos, val);
}
T Get(const int &pos) {
return GetRange(pos, pos + 1);
}
T GetRange(const int &x, const int &y) {
query(1, 0, dim, x, y);
return data[0];
}
};
int main() {
Boost();
int n, m;
fin >> n >> m;
vector < int > v(n);
for(auto &it: v) {
fin >> it;
}
SegmentTree < int > segTree(n);
segTree.MakeTree(v);
while(m--) {
int a, b, c;
fin >> a >> b >> c;
if(a == 0) {
fout << segTree.GetRange(b - 1, c) << "\n";
} else {
segTree.Set(b - 1, c);
}
}
return 0;
}