#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
#ifndef LOCAL_JUDGE
freopen("arbint.in", "r", stdin);
freopen("arbint.out", "w", stdout);
#endif
template<typename type,typename val_type,typename return_type, typename LazyType, typename update_policy, typename query_policy, typename lazy_policy >
class segment_tree
{
vector<type> data;
vector<LazyType> lazy;
update_policy _update_policy;
query_policy _query_policy;
lazy_policy _lazy_policy;
public:
void create(const vector<type> &vec)
{
data.resize(vec.size() * 4);
lazy.resize(vec.size() * 4);
for (int i = 0; i < vec.size() * 4; ++i)
{
_lazy_policy.clear(lazy[i]);
}
for (int i = 0; i < vec.size(); ++i)
{
update(i + 1, i + 1, vec[i], 1, vec.size(), 1);
}
}
void update(int a, int b, val_type v, int x, int y, int k=1)
{
_lazy_policy.to(data[k], lazy[k]);
if (x != y)
{
_lazy_policy.propagate(data[k], data[k * 2], data[k * 2 + 1]);
}
_lazy_policy.clear(lazy[k]);
if (a <= x && y <= b)
{
_update_policy.set(data[k], v);
_lazy_policy.set(lazy[k], v);
return;
}
int mid = (x + y) / 2;
if (a <= mid)
{
update(a, b, v, x, mid, k * 2);
}
if (b > mid)
{
update(a, b, v, mid + 1, y, k * 2 + 1);
}
_lazy_policy.to(data[k*2], lazy[k*2]);
if(k*4 < data.size() && k*4+1 < data.size())
_lazy_policy.propagate(data[k * 2], data[k * 4], data[k * 4 + 1]);
_lazy_policy.clear(data[k*2]);
_lazy_policy.to(data[k * 2 + 1], lazy[k * 2 + 1]);
if (k * 4 + 2 < data.size() && k * 4 + 3 < data.size())
_lazy_policy.propagate(data[k *2 + 1], data[k * 4 + 2], data[k * 4 + 3]);
_lazy_policy.clear(data[k*2+1]);
_update_policy.set(data[k], data[k * 2], data[k * 2 + 1]);
}
return_type query(int a, int b, int x, int y, int k=1)
{
_lazy_policy.to(data[k], lazy[k]);
if (x != y)
{
_lazy_policy.propagate(data[k], data[k * 2], data[k * 2 + 1]);
}
_lazy_policy.clear(lazy[k]);
if (a <= x && y <= b)
{
return _query_policy.get(data[k]);
}
int mid = (x + y) / 2;
if (a <= mid && b > mid)
{
return_type rt1 = query(a, b, x, mid, k * 2);
return_type rt2 = query(a, b, mid + 1, y, k * 2 + 1);
return _query_policy.get(rt1, rt2);
}
if (a <= mid)
{
return query(a, b, x, mid, k * 2);
}
else
{
return query(a, b, mid + 1, y, k * 2 + 1);
}
}
};
class update_policy
{
public:
void set(int& node, const int val)
{
node = val;
}
void set(int &node, const int child_left_node, const int child_right_node)
{
node = max(child_left_node, child_right_node);
}
};
class query_policy
{
public:
int get(const int node)
{
return node;
}
int get(const int child_left_node, const int child_right_node)
{
return max(child_left_node, child_right_node);
}
};
class lazy_policy
{
public:
void clear(int& node)
{
}
void to(int& node, const int value)
{
}
void set(int& node)
{
}
void propagate(int& node, int& child_left_node, int& child_right_node)
{
}
};
segment_tree<int, int, int, int,update_policy, query_policy,lazy_policy> segmentTree;
int main()
{
int N, M;
cin >> N >> M;
vector<int> vec;
for (int i = 1; i <= N; ++i)
{
int x;
cin >> x;
vec.push_back(x);
}
segmentTree.create(vec);
for (int i = 1; i <= M; ++i)
{
int op, a, b;
cin >> op >> a >> b;
if (op == 0)
{
cout << segmentTree.query(a, b, 1, N) <<"\n";
}
else
{
segmentTree.update(a, a, b, 1, N);
}
}
return 0;
}