#include <bits/stdc++.h>
using namespace std;
class sqrt_max_structure {
public:
sqrt_max_structure(const vector<int>& data) :
BUCKET_SIZE((int)sqrt(data.size())),
data_(data),
max_of_bucket_(data.size() / BUCKET_SIZE + 3) {
for (size_t step = 0, i = 0; i < data.size(); ++step, i += BUCKET_SIZE) {
max_of_bucket_[step] = -1;
for (size_t j = i; j < i + BUCKET_SIZE && j < data_.size(); ++j)
max_of_bucket_[step] = max(max_of_bucket_[step], data_[j]);
}
}
void update(size_t position, int value) {
size_t bucket = position / BUCKET_SIZE;
data_[position] = value;
max_of_bucket_[bucket] = -1;
for (size_t i = bucket * BUCKET_SIZE; i < (bucket + 1) * BUCKET_SIZE && i < data_.size(); ++i) {
max_of_bucket_[bucket] = max(max_of_bucket_[bucket], data_[i]);
}
}
int query(size_t left, size_t right) {
int solution = -1;
for (size_t i = left; i < (left / BUCKET_SIZE + 1) * BUCKET_SIZE && i < data_.size() && i <= right; ++i)
solution = max(solution, data_[i]);
for (int i = (int)right; i >= ((int)right / BUCKET_SIZE) * BUCKET_SIZE && i >= (int)left; --i)
solution = max(solution, data_[i]);
for (int i = (int)left / BUCKET_SIZE + 1; i < (int)data_.size() && i < (int)right / BUCKET_SIZE; ++i)
solution = max(solution, max_of_bucket_[i]);
return solution;
}
private:
const int BUCKET_SIZE;
vector< int > data_, max_of_bucket_;
};
class segment_tree {
public:
segment_tree(const vector<int>& data) :
size_(data.size()){
data_.resize(4 * size_);
build(1, 0, data.size() - 1, data);
}
void update(size_t position, int value) {
update(1, 0, size_ - 1, position, value);
}
int query(size_t left, size_t right) {
return query(1, 0, size_ - 1, left, right);
}
private:
void build(int node, size_t left, size_t right, const vector< int >& data) {
if (left == right) {
data_[node] = data[left];
return;
}
size_t middle = (left + right) / 2;
build(2*node, left, middle, data);
build(2*node+1, middle+1, right, data);
data_[node] = max(data_[2*node], data_[2*node+1]);
}
void update(int node, size_t left, size_t right, size_t position, int value) {
if (left == right) {
data_[node] = value;
return;
}
size_t middle = (left + right) / 2;
if (position <= middle)
update(2 * node, left, middle, position, value);
else
update(2 * node + 1, middle + 1, right, position, value);
data_[node] = max(data_[2*node], data_[2*node+1]);
}
int query(int node, size_t left, size_t right, size_t query_left, size_t query_right) {
if (query_left <= left && right <= query_right)
return data_[node];
size_t middle = (left + right) / 2;
int maxim = -1;
if (query_left <= middle)
maxim = max(maxim, query(2*node, left, middle, query_left, query_right));
if (middle < query_right)
maxim = max(maxim, query(2*node+1, middle+1, right, query_left, query_right));
return maxim;
}
size_t size_;
vector< int > data_;
};
void solve() {
size_t size, query_count;
cin >> size >> query_count;
vector< int > values(size);
for (auto& it : values)
cin >> it;
//segment_tree value_manager(values);
sqrt_max_structure value_manager(values);
while (query_count--) {
int operation, a, b;
cin >> operation >> a >> b;
if (operation == 0)
cout << value_manager.query((size_t)a - 1, (size_t)b - 1) << '\n';
else
value_manager.update((size_t)a - 1, b);
}
}
int main() {
assert(freopen("arbint.in", "r", stdin));
assert(freopen("arbint.out", "w", stdout));
cin.tie(nullptr);
ios_base::sync_with_stdio(false);
solve();
return 0;
}