#include <fstream>
#include <iostream>
#include <vector>
#include <cstring>
using namespace std;
ifstream F("arbint.in");
ofstream G("arbint.out");
template <class T, int S>
class SegmentTree {
private:
T hold[S<<2];
T withValue[S<<2];
bool updated[S<<2];
int iBeg;
int iEnd;
T value;
T neutral() {
return T(0);
}
inline void _update_iBeg(int v) {
iBeg = v;
}
inline void _update_iEnd(int v) {
iEnd = v;
}
inline void _update_value(int v) {
value = v;
}
inline int leftIdx(int node) {
return node * 2;
}
inline int rightIdx(int node) {
return node * 2 + 1;
}
T length(int left,int right) {
return right - left + 1;
}
T app(T a, T b, int left, int right) {
return a > b ? a : b;
}
void push(int node, int left, int right) {
if ( !updated[node] )
return;
updated[node] = false;
T nodeValue = withValue[node];
int _leftIdx = leftIdx(node);
int _rightIdx = rightIdx(node);
hold[_leftIdx] = nodeValue;
hold[_rightIdx] = nodeValue;
hold[node] = app(nodeValue, nodeValue, left, right);
withValue[_leftIdx] = nodeValue;
withValue[_rightIdx] = nodeValue;
updated[_leftIdx] = true;
updated[_rightIdx] = true;
}
inline bool isOutside(int left, int right) {
return iBeg > right || iEnd < left;
}
inline bool isInside(int left, int right) {
return iBeg <= left && right <= iEnd;
}
void _update(int node, int left, int right) {
push(node, left, right);
if ( isOutside(left, right) ) {
return;
}
if ( isInside(left, right) ) {
withValue[node] = value;
updated[node] = true;
push(node, left, right);
return;
}
int middle = (left + right) / 2;
int _leftIdx = leftIdx(node);
int _rightIdx = rightIdx(node);
_update(_leftIdx, left, middle);
_update(_rightIdx, middle+1 ,right);
hold[node] = app(hold[_leftIdx], hold[_rightIdx], left, right);
}
T _query(int node, int left, int right) {
push(node, left, right);
if ( isOutside(left, right) ) {
return neutral();
}
if ( isInside(left, right) ) {
return hold[node];
}
int middle = (left + right) / 2;
int _leftIdx = leftIdx(node);
int _rightIdx = rightIdx(node);
T v1 = _query(_leftIdx, left, middle);
T v2 = _query(_rightIdx, middle+1 ,right);
hold[node] = app(hold[_leftIdx], hold[_rightIdx], left, right);
return app(v1, v2, left, right);
}
public:
SegmentTree() {
memset(hold,0,sizeof(hold));
memset(withValue,0,sizeof(withValue));
memset(updated,0,sizeof(updated));
value = neutral();
iBeg = iEnd = 0;
}
int size() {
return S;
}
void update(int iBeg, int iEnd, T value) {
_update_iBeg(iBeg);
_update_iEnd(iBeg);
_update_value(value);
_update(1, 1, S);
}
T query(int iBeg, int iEnd) {
_update_iBeg(iBeg);
_update_iEnd(iEnd);
return _query(1, 1, S);
}
};
const int N = 200010;
SegmentTree<int,N> *seg = new SegmentTree<int,N>();
int n, m;
int main() {
F >> n >> m;
for (int i = 1, x; i <= n; ++i) {
F >> x;
seg -> update(i, i, x);
}
for (int i = 1, t, x, y; i <= m; ++i) {
F >> t >> x >> y;
if ( t == 1 ) {
seg -> update(x, x, y);
} else {
int ans = seg -> query(x, y);
G << ans << '\n';
}
}
}