// if this gets accepted i'm drinking tonight
#define use_fast_io (std::ios::sync_with_stdio(false); std::cin.tie(nullptr); std::cout.tie(nullptr);)
#define file_io(s) freopen(((std::string)s + ".in").c_str(), "r", stdin); freopen(((std::string)s + ".out").c_str(), "w", stdout)
#define all(a) (a.begin(), a.end())
#define range(a,i,j) (a.begin() + (i), a.begin() + (j))
#define aall(a, n) ((a, a + 1))
#define arange(a,i,j) ((a + (i), a + (j)))
const int NMAX = 1e5 + 8;
#include <iostream>
using namespace std;
template<typename tp>
class seg_tree {
private:
int n;
tp data[NMAX * 4];
//! -------- replace these ---------
static const tp __zero = -1;
tp __merge(const tp& i, const tp& j) {
return max(i, j);
}
//! --------------------------------
void __init(int node, int left, int right, tp *a) {
if (left == right) {
data[node] = a[left];
return;
}
int mid = (left + right) / 2;
int left_child = 2 * node;
int right_child = 2 * node + 1;
__init(left_child, left, mid, a);
__init(right_child, mid + 1, right, a);
data[node] = __merge(data[left_child], data[right_child]);
}
tp __range_query(int node, int left, int right, int q_left, int q_right) {
if (q_left <= left && right <= q_right) {
return data[node];
}
int mid = (left + right) / 2;
int left_child = 2 * node;
int right_child = 2 * node + 1;
tp ans = __zero;
if (q_left <= mid)
ans = __merge(ans, __range_query(left_child, left, mid, q_left, q_right));
if (mid + 1 <= q_right)
ans = __merge(ans, __range_query(right_child, mid + 1, right, q_left, q_right));
return ans;
}
void __point_update(int node, int left, int right, int index, const tp& val) {
if (left == right) {
data[node] = val;
return;
}
int mid = (left + right) / 2;
int left_child = 2 * node;
int right_child = 2 * node + 1;
if (index <= mid)
__point_update(left_child, left, mid, index, val);
else
__point_update(right_child, mid + 1, right, index, val);
data[node] = __merge(data[left_child], data[right_child]);
}
public:
seg_tree<tp>() {};
void init(int n, tp *a) {
this->n = n;
__init(1, 1, n, a);
}
tp point_query(int index) {
return __range_query(1, 1, n, index, index);
}
tp range_query(int left, int right) {
return __range_query(1, 1, n, left, right);
}
void update(int index, const tp& value) {
__point_update(1, 1, n, index, value);
}
};
int n, m;
int a[NMAX];
seg_tree<int> st_max;
int main() {
file_io("arbint");
cin >> n >> m;
for (int i = 1; i <= n; ++i) {
cin >> a[i];
}
st_max.init(n, a);
for (int i = 1; i <= m; ++i) {
int op, a, b;
cin >> op >> a >> b;
if (op == 1) {
st_max.update(a, b);
}
else {
cout << st_max.range_query(a, b) << '\n';
}
}
return 0;
}
// Made in Romania