#include <vector>
#include <iostream>
#include <stdint.h>
#include <algorithm>
#include <bitset>
#include <queue>
#include <climits>
#define int long long
using namespace std;
//std::ifstream cin("paralele.in");
//std::ofstream cout("paralele.out");
struct AINT {
AINT(int _n) {
n = _n;
tree.resize(n*4 + 5);
}
void Build() {
build(1,n,1);
}
void Update(int i,int x) {
update(1,n,1,i,x);
}
int Query(int i,int j) {
qrez = LONG_MIN;
query(1,n,1,i,j);
return qrez;
}
private:
std::vector<int> tree;
int n;
int qrez;
void build(int st,int dr,int node) {
if (st == dr) {
cin>>tree[node];
return;
}
int mid = (st + dr)/2;
build(st,mid,node*2);
build(mid+1,dr,node*2+1);
tree[node] = std::max(tree[2*node],tree[2*node+1]);
}
void update(int st,int dr,int node,int i,int x) {
if (st == dr) {
tree[node] = x;
return;
}
int mid = (st+dr)/2;
if (i <= mid) {
update(st,mid,node*2,i,x);
}
if (i > mid) {
update(mid+1,dr,node*2+1,i,x);
}
tree[node] = std::max(tree[2*node],tree[2*node+1]);
}
void query(int st,int dr,int node,int i,int j) {
if (i <= st && dr <= j) {
qrez = std::max(qrez,tree[node]);
return;
}
int mid = (st+dr)/2;
if (i <= mid) {
query(st,mid,node*2,i,j);
}
if (j >= mid+1) {
query(mid+1,dr,node*2+1,i,j);
}
}
};
signed main() {
int n,q;
cin>>n>>q;
AINT aint(n);
aint.Build();
for (int i=1; i<=q; i++) {
int c,a,b;
cin>>c>>a>>b;
if (c == 1) {
aint.Update(a,b);
}
else {
cout<<aint.Query(a,b)<<"\n";
}
}
}