//ehg
#include <bits/stdc++.h>
using namespace std;
# define out(n) printf("%d \n", n)
# define in(n) scanf("%d", &n)
char slash = '\n',space = ' ';
int M, N, A, i, a, b;
bool taskCode;
void scan();
int getMid(int left, int right) { return left + (right - left)/2; }
void updategradually(int *tree, int left, int right, int pos, int val, int node);
int getMax(int *tree, int left, int right, int a, int b, int node);
int main()
{
freopen("arbint.in", "r", stdin);
freopen("arbint.out", "w", stdout);
scan();
return 0;
}
void scan()
{
in(N), in(M);
int maxSize = 2 * (pow(2, (int)(ceil(log2(N))))) - 1;
int *tree = new int[maxSize];
memset(tree, 0, maxSize*4);
int var;
for (i = 0; i < N; i++)
{
in(var);
updategradually(tree, 0, N - 1, i, var, 0);
}
while(M--)
{
in(taskCode), in(a), in(b);
if (!taskCode)
out(getMax(tree, 0, N - 1, a - 1, b - 1, 0));
else
updategradually(tree, 0, N - 1, a - 1, b, 0);
}
delete[] tree;
}
void updategradually(int *tree, int left, int right, int pos, int val, int node)
{
if (pos < left || right < pos)
return;
if (left == right)
{
tree[node] = val;
return;
}
int mid = getMid(left, right);
updategradually(tree, left, mid, pos, val, 2*node + 1);
updategradually(tree, mid + 1, right, pos, val, 2*node + 2);
tree[node] = tree[2*node + 1] > tree[2*node + 2] ? tree[2*node + 1] : tree[2*node + 2];
}
int getMax(int *tree, int left, int right, int a, int b, int node)
{
if (right < a || left > b)
return 0;
if (a <= left && right <= b)
{
return tree[node];
}
int mid = getMid(left, right);
int ans1 = getMax(tree, left, mid, a, b, 2*node + 1);
int ans2 = getMax(tree, mid + 1, right, a, b, 2*node + 2);
return ans1 > ans2 ? ans1 : ans2;
}