#include <bits/stdc++.h>
using namespace std;
using ll = long long int;
using ld = long double;
using VI = vector<ll>;
using VD = vector<ld>;
using VVI = vector<VI>;
using VC = vector<char>;
using VVC = vector<VC>;
using VS = vector<string>;
using PLL = pair<ll, ll>;
using PLD = pair<ld, ld>;
using VPLL = vector<PLL>;
#define REP(i, n) for (ll i = 0; i < (ll)(n); i++)
#define REPD(i, n) for (ll i = (ll)(n)-1; i >= 0; i--)
#define FOR(i, a, b) for (ll i = (a); i <= (b); i++)
#define FORD(i, a, b) for (ll i = (a); i >= (b); i--)
#define ALL(x) (x).begin(), (x).end()
#define ALLR(x) (x).rbegin(), (x).rend()
#define SIZE(x) ((ll)(x).size())
#define MAX(x) *max_element((x).begin(), (x).end())
#define MIN(x) *min_element((x).begin(), (x).end())
#define SORTR(x) sort((x).rbegin(), (x).rend())
#define SORT(x) sort((x).begin(), (x).end())
#define SUM(x) accumulate((x).begin(), (x).end(), 0)
#define FILL(x, a) fill(x.begin(), x.end(), a)
#define EACH(i, x)                                                             \
  for (typeof((x).begin()) i = (x).begin(); i != (x).end(); ++i)

const long long  int INF = 1e18;
const ld EPS = 1e-10;
const int MOD = int(1e9) + 7;
template<class T> bool chmax(T& a, const T& b)
{
  if (a < b)
  {
    a = b;
    return 1;
  }
  return 0;
}
template<class T> bool chmin(T& a, const T& b)
{
  if (b < a)
  {
    a = b;
    return 1;
  }
  return 0;
}
template<class BidirectionalIterator>
bool next_partial_permutation(BidirectionalIterator first,
    BidirectionalIterator middle,
    BidirectionalIterator last)
{
  reverse(middle, last);
  return next_permutation(first, last);
}
#define COUT(x) cout << x << "\n"

class SegmentTree
{
private:
    int n;
    int size;
    vector<ll> node;

public:
    // 元配列 v をセグメント木で表現する
    SegmentTree(vector<ll> v)
    {
      // 最下段のノード数は元配列のサイズ以上になる最小の 2倍 -> これを n とおく
      // セグメント木全体で必要なノード数は 2n-1 個である
      size = v.size();
      n = 1;
      while (n < size) n *= 2;
      node.resize(2 * n - 1, INF);
      // 最下段に値を入れたあとに、下の段から順番に値を入れる
      // 値を入れるには、自分の子の 2 値を参照すれば良い
      for (ll i = 0; i < size; i++)
        node[i + n - 1] = v[i];
      for (ll i = n - 2; i >= 0; i--)
        node[i] = min(node[2 * i + 1], node[2 * i + 2]);
    }

    void update(ll x, ll val)
    {
      // 最下段のノードにアクセスする
      x += (n - 1);

      // 最下段のノードを更新したら、あとは親に上って更新していく
      node[x] = val;
      while (x > 0)
      {
        x = (x - 1) / 2;
        node[x] = min(node[2 * x + 1], node[2 * x + 2]);
      }
    }

    // 要求区間 [a, b) 中の要素の最小値を答える
    // k := 自分がいるノードのインデックス
    // 対象区間は [l, r) にあたる
    ll getmin(ll a, ll b, ll k=0, ll l=0, ll r=-1) {
      // 最初に呼び出されたときの対象区間は [0, n)
      if(r < 0) r = n;
      // 要求区間と対象区間が交わらない -> 適当に返す
      if(r <= a || b <= l) return INF;
      // 要求区間が対象区間を完全に被覆 -> 対象区間を答えの計算に使う
      if(a <= l && r <= b) return node[k];
      // 要求区間が対象区間の一部を被覆 -> 子について探索を行う
      // 左側の子を vl ・ 右側の子を vr としている
      // 新しい対象区間は、現在の対象区間を半分に割ったもの
      ll vl = getmin(a, b, 2*k+1, l, (l+r)/2);
      ll vr = getmin(a, b, 2*k+2, (l+r)/2, r);
      return min(vl, vr);
    }

};

void Main()
{
  ll N, Q;
  cin>>N>>Q;
  ll ini=pow(2,31)-1;
  SegmentTree seg(VI(N,ini));

  REP(i,Q){
    ll c,x,y;
    cin>>c>>x>>y;
    if(c==0) seg.update(x,y);
    else COUT(seg.getmin(x,y+1));
  }
  return;
}

int main()
{
  std::cin.tie(0);
  std::ios_base::sync_with_stdio(false);
  std::cout << std::fixed << std::setprecision(15);
  Main();
}



Measured memory_bytes: 5760