#include <cstdio>
#include <cstdlib>
#include <vector>
#include <cmath>
#include <climits>
using namespace std;
FILE *fin, *fout;
const int NMAX = 1e5;
int n, v[NMAX + 5];
const int INF = INT_MAX;
int maxright;
vector <int> aint;
void build(int node, int left = 1, int right = maxright)
{
if(left == right and left > n)
{
aint[node] = INF;
return;
}
if(left == right)
{
aint[node] = v[left];
return;
}
int mid = (left + right) / 2;
build(2 * node, left, mid);
build(2 * node + 1, mid + 1, right);
aint[node] = max(aint[2 * node], aint[2 * node + 1]);
}
int query(int leftint, int rightint, int node = 1, int left = 1, int right = maxright)
{
if(leftint <= left and rightint >= right)
return aint[node];
int mid = (left + right) / 2;
int leftans = 0 , rightans = 0;
if(leftint <= mid)
leftans = query(leftint , rightint , 2 * node , left , mid);
if(rightint > mid)
rightans = query(leftint , rightint , 2 * node + 1 , mid + 1 , right);
return max(leftans , rightans);
}
void update(int pos, int value, int node = 1, int left = 1, int right = maxright)
{
if(left == right and left > n and right > n)
{
aint[node] = INF;
return;
}
if(left == right)
{
aint[node] = value;
return;
}
int mid = (left + right) / 2;
if(pos <= mid)
{
update(pos, value, 2 * node, left, mid);
}
else
{
update(pos, value, 2 * node + 1, mid + 1, right);
}
aint[node] = max(aint[2 * node], aint[2 * node + 1]);
}
int main()
{
fin = fopen("arbint.in", "r");
fout = fopen("arbint.out", "w");
int m;
fscanf(fin, "%d%d", &n, &m);
for(int i = 1; i <= n; i++)
fscanf(fin, "%d", &v[i]);
int exp = log2(n) , nodes;
if(1 << exp == n)
{
nodes = 2 * (1 << exp) - 1;
}
else
{
exp++;
nodes = 2 * (1 << exp) - 1;
}
aint.resize(nodes + 5);
maxright = 1 << exp;
build(1, 1, maxright);
for(int i = 1; i <= m; i++)
{
int op, a, b;
fscanf(fin, "%d%d%d", &op, &a, &b);
if(op == 0)
{
fprintf(fout, "%d\n", query(a, b));
}
else if(op == 1)
{
update(a, b);
}
}
fclose(fin);
fclose(fout);
return 0;
}