#include <stdio.h>
#include <stdlib.h>
#define MAXN 100000
#define MAX_TREE_SIZE 262144 // 2 * (2^ceil(log2(MAXN)))
long long segment_tree[MAX_TREE_SIZE];
long long A[MAXN];
int N, M;
void build_tree(int node, int start, int end) {
if (start == end) {
segment_tree[node] = A[start];
} else {
int mid = start + (end - start) / 2;
build_tree(2 * node + 1, start, mid);
build_tree(2 * node + 2, mid + 1, end);
segment_tree[node] = (segment_tree[2 * node + 1] > segment_tree[2 * node + 2]) ? segment_tree[2 * node + 1] : segment_tree[2 * node + 2];
}
}
void update_tree(int node, int start, int end, int i, long long val) {
if (start == end) {
A[i] = val;
segment_tree[node] = val;
} else {
int mid = start + (end - start) / 2;
if (start <= i && i <= mid) {
update_tree(2 * node + 1, start, mid, i, val);
} else {
update_tree(2 * node + 2, mid + 1, end, i, val);
}
segment_tree[node] = (segment_tree[2 * node + 1] > segment_tree[2 * node + 2]) ? segment_tree[2 * node + 1] : segment_tree[2 * node + 2];
}
}
long long query_tree(int node, int start, int end, int L, int R) {
if (R < start || end < L) {
return -1;
}
if (L <= start && end <= R) {
return segment_tree[node];
}
int mid = start + (end - start) / 2;
long long p1 = query_tree(2 * node + 1, start, mid, L, R);
long long p2 = query_tree(2 * node + 2, mid + 1, end, L, R);
return (p1 > p2) ? p1 : p2;
}
int main() {
FILE *in = fopen("arbint.in", "r");
FILE *out = fopen("arbint.out", "w");
fscanf(in, "%d %d", &N, &M);
for (int i = 0; i < N; i++) {
fscanf(in, "%lld", &A[i]);
}
build_tree(0, 0, N - 1);
while(M--) {
int type, a, b;
fscanf(in, "%d %d %d", &type, &a, &b);
if (type == 0) {
fprintf(out, "%lld\n", query_tree(0, 0, N - 1, a - 1, b - 1));
} else if (type == 1) {
update_tree(0, 0, N - 1, a - 1, b);
}
}
fclose(in);
fclose(out);
return 0;
}