#include<map>
#include<set>
#include<list>
#include<cmath>
#include<queue>
#include<stack>
#include<cstdio>
#include<string>
#include<vector>
#include<complex>
#include<cstdlib>
#include<cstring>
#include<numeric>
#include<sstream>
#include<iostream>
#include<algorithm>
#include<functional>

#define mp       make_pair
#define pb       push_back
#define all(x)   (x).begin(),(x).end()
#define rep(i,n) for(int i=0;i<(n);i++)
#define MAX 1000001

using namespace std;

typedef    long long          ll;
typedef    unsigned long long ull;
typedef    vector<bool>       vb;
typedef    vector<int>        vi;
typedef    vector<vb>         vvb;
typedef    vector<vi>         vvi;
typedef    pair<int,int>      pii;

const int INF=1<<29;
const double EPS=1e-9;

const int dx[]={1,0,-1,0},dy[]={0,-1,0,1};
const int MAX_N =1<<31-1;

//segment-tree
int n;//nは2のべき乗
int dat[1000001*2-1];
int na;
//初期化
void init(){
	//すべての値をINT_MAXに
	for(int i =0;i <2*n-1;i++){
		dat[i]=INT_MAX;
	}
}

//i番目の値(0-indexed)をxに変更
void update(int i,int x){
	//葉のノード番号
	i += na - 1;
	dat[i] = x;
	while(i >0){
		i =(i-1)/2;
		dat[i] =min(dat[i*2+1],dat[i*2+2]);
	}
}

//[a,b)の最小値,l,rにはノードkに対応づく区画を与える
//外からはquery(a,b,0,0,n)のように呼ぶ
int query(int a,int b,int k,int l,int r){
	if(r <=a||b <=l)//交差しない
		return INT_MAX;
	if(a <=l&&r<=b)//完全に含む
		return dat[k];
	else{
		int vl =query(a, b, k*2+1, l, (l+r)/2);
		int vr =query(a, b, k*2+2, (l+r)/2, r);
		return min(vl,vr);
	}
}
int q;
int main(){
	cin>>n>>q;
	na = 1;
	na =na<<n;
	for(int i=0;i<MAX*2-1;i++) dat[i] = INT_MAX;
	int c,x,y;
	while(q--){
		scanf("%d %d %d",&c,&x,&y);
		if(!c)
			update(x,y);
		else
			printf("%d\n",query(x,y+1,0,0,na));
	}
	return 0;
}