#include<stdio.h>
#include <iostream>
#include <math.h>
#include <numeric>
#include <vector>
#include <map>
#include <functional>
#include <stdio.h>
#include <array>
#include <algorithm>
#include <string>
#include <string.h>
#include <assert.h>
#include <stdio.h>
#include <queue>
#include<iomanip>
#include<bitset>
#include<stack>
#include<set>
#include<limits>
#include <complex>
using namespace std;
template < class BidirectionalIterator >
bool next_combination(BidirectionalIterator first1,
	BidirectionalIterator last1,
	BidirectionalIterator first2,
	BidirectionalIterator last2)
{
	if ((first1 == last1) || (first2 == last2)) {
		return false;
	}
	BidirectionalIterator m1 = last1;
	BidirectionalIterator m2 = last2; --m2;
	while (--m1 != first1 && !(*m1 < *m2)) {
	}
	bool result = (m1 == first1) && !(*first1 < *m2);
	if (!result) {
		// ?
		while (first2 != m2 && !(*m1 < *first2)) {
			++first2;
		}
		first1 = m1;
		std::iter_swap(first1, first2);
		++first1;
		++first2;
	}
	if ((first1 != last1) && (first2 != last2)) {
		// ?
		m1 = last1; m2 = first2;
		while ((m1 != first1) && (m2 != last2)) {
			std::iter_swap(--m1, m2);
			++m2;
		}
		// ?
		std::reverse(first1, m1);
		std::reverse(first1, last1);
		std::reverse(m2, last2);
		std::reverse(first2, last2);
	}
	return !result;
}

template < class BidirectionalIterator >
bool next_combination(BidirectionalIterator first,
	BidirectionalIterator middle,
	BidirectionalIterator last)
{
	return next_combination(first, middle, middle, last);
}



class Compare {
public:
	bool operator()(const pair<int,long long  int>&l, const pair<int, long long int >&r) {
		return l.second > r.second;
	}
};






#define _GLIBCXX_DEBUG
#include <iostream>
#include <vector>

using namespace std;

#define REP(i,n) for(int i=0;i<(int)n;++i)
#define FOR(i,c) for(auto i=(c).begin();i!=(c).end();++i)
#define ALL(c) (c).begin(), (c).end()

const int INF = 2147483647;
const long long int L_INF = 9223372036854775807;

typedef int Weight;
struct Edge {
	int src, dst;
	Weight weight;
	Edge(int src, int dst, Weight weight) :
		src(src), dst(dst), weight(weight) { }
};
bool operator < (const Edge &e, const Edge &f) {
	return e.weight != f.weight ? e.weight > f.weight : // !!INVERSE!!
	e.src != f.src ? e.src < f.src : e.dst < f.dst;
}
typedef vector<Edge> Edges;
typedef vector<Edges> Graph;

typedef vector<Weight> Array;
typedef vector<Array> Matrix;
#define RESIDUE(s,t) (capacity[s][t]-flow[s][t])

vector<pair<int, int>>uses;

//流量0の逆辺も張らないと正しく求まらないので注意
Weight maximumFlow(const Graph &ag, int s, int t) {

	Graph g(ag);
	for (int i = 0; i < ag.size(); ++i) {
		for (int j = 0; j < ag[i].size(); ++j) {
			int d = ag[i][j].dst;
			int s = ag[i][j].src;
			
			bool ok = false;
			for (int k = 0; k < ag[d].size(); ++k) {
				if (ag[d][k].src == s) {
					ok = true;
					break;
				}
			}
			if (!ok) {
				g[d].push_back(Edge(d, s, 0));
			}
		}
	}

	int n = g.size();
	Matrix flow(n, Array(n)), capacity(n, Array(n));
	REP(u, n) FOR(e, g[u]) capacity[e->src][e->dst] += e->weight;

	Weight total = 0;
	while (1) {
		queue<int> Q; Q.push(s);
		vector<int> prev(n, -1); prev[s] = s;
		while (!Q.empty() && prev[t] < 0) {
			int u = Q.front(); Q.pop();
			FOR(e, g[u]) if (prev[e->dst] < 0 && RESIDUE(u, e->dst) > 0) {
				prev[e->dst] = u;
				Q.push(e->dst);
			}
		}
		if (prev[t] < 0) return total; // prev[x] == -1 <=> t-side
		Weight inc = INF;
		for (int j = t; prev[j] != j; j = prev[j])
			inc = min(inc, RESIDUE(prev[j], j));
		for (int j = t; prev[j] != j; j = prev[j])
			flow[prev[j]][j] += inc, flow[j][prev[j]] -= inc;
		total += inc;
	}
}

struct vert {
	int deg;
	int s;
	int id;
	vert(int a, int b, int c) {
		deg = a;
		s = b;
		id = c;
	}
};

#define N (1<<17) 
// update(l,r,v) := [l,r]の区間に対してvを一様に足す. k,a,bは飾り

struct NODE {
	int sum;//更新された値. この値を参照する時は評価が完全に完了しているようにする.
	int lazy;	//遅延されている値を保存している
	NODE() {
		sum = lazy = 0;
	}
};

NODE seg[2 * N];

// inlineつけないと大変なことになるよ!(遅い)
inline void lazy_evaluate_node(int k, int a, int b) {
	seg[k].sum += seg[k].lazy * (b - a + 1);
	if (k < N) { // 2*k(左の子番号) < 2*N (節点の数) のイメージで. 末端ノードじゃなきゃ伝搬するのと等価.
		seg[2 * k].lazy += seg[k].lazy;	//次は君が伝搬してね☆って感じ.
		seg[2 * k + 1].lazy += seg[k].lazy;
	}
	seg[k].lazy = 0;
}

inline void update_node(int k) { // kの子が既に評価されていることが前提. 末端以外のときしか呼び出さないような位置に書くのでif文要らない.
	seg[k].sum = seg[2 * k].sum + seg[2 * k + 1].sum;
}

// update(l,r,v) := [l,r]を更新する. 区間は1-indexed.
void update(int l, int r, int v, int k = 1, int a = 1, int b = N) {
	lazy_evaluate_node(k, a, b); 	// とりあえず辿ったノードは都合がいいので伝搬しとけ精神.

	if (b < l || r < a) //[a,b]と[l,r]が交差している場合
		return;
	if (l <= a && b <= r) { // [l,r]が[a,b]を完全に含んでいる場合
		seg[k].lazy += v;
		lazy_evaluate_node(k, a, b); //一回遅延評価しとかないと都合悪いので.
		return;
	}

	int m = (a + b) / 2;
	update(l, r, v, 2 * k, a, m);
	update(l, r, v, 2 * k + 1, m + 1, b);
	update_node(k);
}

// get(l,r) := [l,r]に対するクエリの答えを得る. 区間は1-indexed.
int get(int l, int r, int k = 1, int a = 1, int b = N) {
	lazy_evaluate_node(k, a, b); // とりあえず辿ったノードは都合がいいので伝搬しとけ精神.

	if (b < l || r < a) //[a,b]と[l,r]が交差している場合
		return 0;

	if (l <= a && b <= r) { // [l,r]が[a,b]を完全に含んでいる場合
		return seg[k].sum;
	}

	int m = (a + b) / 2;
	int vl = get(l, r, 2 * k, a, m);
	int vr = get(l, r, 2 * k + 1, m + 1, b);
	update_node(k);
	return vl + vr;
}

class Hei {


public:
	const int normalsize;
	vector<pair<vector<long long int>, long long int>>squares;


	Hei(const int n,const long long int initializenum) :normalsize(sqrt(n)){
		int rest = n;
		while (rest > 0) {
			squares.push_back(make_pair(vector<long long int>(min(rest,normalsize), initializenum), initializenum));
			rest -= normalsize;
		}
	}

	void update(const long long int i, const long long int x) {
		int square = i/normalsize;
		squares[square].first[i - square*normalsize] = x;
		long long int amin(INF);
		for (int i = 0; i < squares[square].first.size(); ++i) {
			amin = min(squares[square].first[i], amin);
		}
		squares[square].second = amin;
	}

	//[l,r]
	long long int get(const int l,const int r) {
		assert(l<=r);
		
		int lsquare = l/normalsize;
		int rsquare = r/normalsize;
		if (lsquare == rsquare) {
			long long int amin(INF);
			for (int i = l - lsquare*normalsize; i <= r - rsquare*normalsize; ++i) {
				amin = min(amin,squares[lsquare].first[i]);
			}
			return amin;
		}
		else {
			long long int amin(INF);
			for (int i = l - lsquare*normalsize; i < squares[lsquare].first.size(); ++i) {
				amin = min(amin,squares[lsquare].first[i]);
			}
			for (int i = lsquare + 1; i < rsquare; ++i) {
				amin = min(amin, squares[i].second);
			}
			for (int i =0; i <= r - rsquare*normalsize; ++i) {
				amin = min(amin, squares[rsquare].first[i]);
			}
			return amin;
		}
		
	}

};

int main() {

	
	
	//int N; cin >> N;
	//vector<vector<int>>edges(N);
	//vector<vert>es;
	//for (int i = 0; i < N; ++i) {
	//	int degree, s; cin >> degree >> s;
	//	es.push_back(vert(degree,s,i));
	//}
	//vector<vert>sortes(es);
	////sort(sortes.begin(), sortes.end(), [](const vert&l, vert&r) {return l.deg < r.deg; });
	//for (int i = 0; i < sortes.size(); ++i) {
	//	if (sortes[i].deg == 1) {
	//		int  nowid(i);
	//		while (sortes[nowid].deg == 1) {
	//			sortes[nowid].deg--;
	//			edges[nowid].push_back(sortes[nowid].s);
	//			sortes[sortes[nowid].s].s ^= sortes[nowid].id;
	//			sortes[sortes[nowid].s].deg--;
	//			nowid = sortes[sortes[nowid].s].id;
	//		}
	//	}
	//}
	//int ans = 0;
	//for (int i = 0; i < N; ++i) {
	//	for (int j = 0; j < edges[i].size(); ++j) {
	//		ans++;
	//	}
	//}
	//cout << ans << endl;
	//for (int i = 0; i < N; ++i) {
	//	for (int j = 0; j < edges[i].size(); ++j) {
	//		cout << i << " " << edges[i][j] << endl;
	//	}
	//}

	/*int n; cin >> n;
	vector<int>sinsuus(n);
	for (int j = 0; j < 2; ++j) {


		vector<int>nums;
		for (int i = 0; i < n; ++i) {
			int a; cin >> a;
			nums.push_back(a);
		}


		for (int i = 0; i < n; ++i) {
			int pl = get(nums[i], nums[i]);
			update(nums[i], n, 1);
			sinsuus[i] += nums[i] - (pl);
		}
		int k;
		for (int i = 0; i < 2 * N; ++i) {
			seg[i] = NODE();
		}
	}
	for (int i = n- 1; i >= 0; --i) {
		if (sinsuus[i] >= n-i) {
			if(i!=0)
				sinsuus[i- 1]++;
			sinsuus[i] -= n-i;
		}
	}

	vector<int>ansnums(n);



	for (int i = 0; i < n; ++i) {
		ansnums[i] = sinsuus[i]+get(0,sinsuus[i]-1);
		update(sinsuus[i], sinsuus[i], 1);
	}
	
	return 0;*/


	long long int n, q; cin >> n >> q;
	Hei hei(n,INF);
	for (int i = 0; i < q; ++i) {
		long long int com, x, y; cin >> com >> x >> y;
		if (com) {
			long long int ans(hei.get(x, y));
			cout << ans << endl;
		}
		else {
			hei.update(x, y);
		}
	}
	return 0;
}

Measured memory_bytes: 5808