#include <fstream>
#include <algorithm>
using namespace std;
#define MAX_ARBINT ((1 << 18) + 1)
ifstream fIn("arbint.in");
ofstream fOut("arbint.out");
int n, queries, arbInt[MAX_ARBINT];
int getMax(int currPos, int leftPos, int rightPos, int currLeft,
int currRight) {
if (leftPos <= currLeft && rightPos >= currRight) {
return arbInt[currPos];
}
if (leftPos > currRight || rightPos < currLeft) {
return -1;
}
int midPos = (currLeft + currRight) / 2;
return max(getMax(currPos * 2, leftPos, rightPos, currLeft, midPos),
getMax(currPos * 2 + 1, leftPos, rightPos, midPos + 1, currRight));
}
void updatePos(int currPos, int posInVector, int leftPos, int rightPos, int newVal) {
if (leftPos == rightPos) {
arbInt[currPos] = newVal;
return;
}
int midPos = (leftPos + rightPos) / 2;
if (posInVector <= midPos) {
updatePos(currPos * 2, posInVector, leftPos, midPos, newVal);
} else {
updatePos(currPos * 2 + 1, posInVector, midPos + 1, rightPos, newVal);
}
arbInt[currPos] = max(arbInt[currPos * 2], arbInt[currPos * 2 + 1]);
}
int main() {
char c;
int x, y;
fIn >> n >> queries;
for (register int i = 1; i <= n; ++i) {
fIn >> x;
updatePos(1, i, 1, n, x);
}
for (register int i = 0; i < queries; ++i) {
fIn >> c >> x >> y;
switch(c) {
case '0':
fOut << getMax(1, x, y, 1, n) << '\n';
break;
case '1':
updatePos(1, x, 1, n, y);
break;
}
}
fIn.close();
fOut.close();
return 0;
}