#include <bits/stdc++.h> // {{{

#define GET_MACRO(a, b, c, d, NAME, ...) NAME
#define REP(...) GET_MACRO(__VA_ARGS__, REP4, REP3, REP2)(__VA_ARGS__)
#define REP2(i, a) REP3(i, 0, a)
#define REP3(i, a, b) REP4(i, a, b, 1)
#define REP4(i, a, b, s) for (int i = (a); i < (int)(b); i += (s))
#define REPR(...) GET_MACRO(__VA_ARGS__, REPR4, REPR3, REPR2)(__VA_ARGS__)
#define REPR2(i, a) REPR3(i, 0, a)
#define REPR3(i, a, b) REPR4(i, a, b, 1)
#define REPR4(i, a, b, s) for (int i = (b)-1; i >= (int)(a); i -= (s))
#define ALL(c) (c).begin(), (c).end()
#define DUMP(x) (std::cerr << #x << ':' << ' ' << x << '\n')
#define TMPL_T template <typename T>
#define TMPL_TU template <typename T, typename U>
#define mut auto
#define let const auto

using Int = long long;
// clang-format off
namespace extio {
std::string delimiter=" ",pdelimiter=" ";
std::string bracket_b="",bracket_e="";
void chdelim(const std::string&s){delimiter=s;}
void chpdelim(const std::string&s){pdelimiter=s;}
void chbracket(const std::string&b,const std::string&e){bracket_b=b,bracket_e=e;}
TMPL_T  void pcont(std::ostream&os,const T&x){int c=0;for(const auto&a:x){if(c++)os<<delimiter;os<<a;}}
TMPL_TU void ppair(std::ostream&os,const std::pair<T,U>&p){os<<bracket_b<<p.first<<pdelimiter<<p.second<<bracket_e;}
}
namespace std {
TMPL_T ostream& operator<<(ostream&os,const vector<T>&x){extio::pcont(os,x);return os;}
TMPL_T ostream& operator<<(ostream&os,const set<T>&x){extio::pcont(os,x);return os;}
TMPL_T ostream& operator<<(ostream&os,const multiset<T>&x){extio::pcont(os,x);return os;}
TMPL_T ostream& operator<<(ostream&os,const deque<T>&x){extio::pcont(os,x);return os;}
TMPL_TU ostream& operator<<(ostream&os,const map<T,U>&x){extio::pcont(os,x);return os;}
TMPL_TU ostream& operator<<(ostream&os,const pair<T,U>&x){extio::ppair(os,x);return os;}
}
TMPL_TU inline bool chmax(T&x,U a){return x<a&&(x=a,1);}
TMPL_TU inline bool chmin(T&x,U a){return a<x&&(x=a,1);}

inline int in(){int x;std::cin>>x;return x;}

struct Initializer_ {
  Initializer_(){
    std::cin.tie(0);
    std::ios::sync_with_stdio(0);
    std::cout << std::setprecision(10);
    std::cerr << std::setprecision(10);
  }
} precalc;
// clang-format on
// }}}

// {{{ rbst.hpp
#ifndef INCLUDE_RBST_HPP
#define INCLUDE_RBST_HPP

#include <cassert>
#include <cstdint>
#include <utility>

namespace misc {
template <typename T>
using twins = std::pair<T, T>;
using rint_t = std::uint32_t;

rint_t xor128() {
  static rint_t x = 123456789, y = 362436069, z = 521288629, w = 88675123;
  rint_t t = x ^ (x << 11);
  x = y;
  y = z;
  z = w;
  return w = (w ^ (w >> 19)) ^ (t ^ (t >> 8));
}
}

namespace orliv {

template <typename StateType>
struct RBST {
  struct Node;
  using self_t = RBST<StateType>;
  using state_t = typename std::remove_const<StateType>::type;
  using size_t = misc::rint_t;
  using node_ptr = Node *;
  using np_twins = misc::twins<node_ptr>;
  using rb_twins = misc::twins<self_t>;

private:
  node_ptr root;

public:
  RBST() : root(Node::null) {}
  RBST(node_ptr root) : root(root) {}

  template <typename... Types>
  static self_t create(Types... args) {
    return self_t(
        (new Node(std::move(state_t(std::forward<Types>(args)...))))->update());
  }

  static node_ptr merge(node_ptr L, node_ptr R) {
    if (!L->size) return R;
    if (!R->size) return L;

    if (misc::xor128() % (L->size + R->size) < L->size) {
      L->R = merge(L->R, R);
      return L->update();
    } else {
      R->L = merge(L, R->L);
      return R->update();
    }
  }
  static np_twins split(node_ptr x, size_t k) {
    assert(k <= x->size);
    if (!x->size) return np_twins(Node::null, Node::null);
    if (k <= x->L->size) {
      auto s = split(x->L, k);
      x->L = s.second;
      s.second = x->update();
      return s;
    } else {
      auto s = split(x->R, k - x->L->size - 1);
      x->R = s.first;
      s.first = x->update();
      return s;
    }
  }

  const Node *const operator->() const { return root; }

  self_t mergeL(self_t x) {
    root = merge(x.root, root);
    return *this;
  }
  self_t mergeR(self_t x) {
    root = merge(root, x.root);
    return *this;
  }
  static self_t merge(self_t L, self_t R) { return L.mergeR(R); }
  rb_twins split(size_t k) const {
    auto s = split(root, k);
    return rb_twins(self_t(s.first), self_t(s.second));
  }
  const state_t range(size_t l) const { return range(l, root->size); }
  const state_t range(size_t l, size_t r) {
    assert(l < r);
    auto s1 = split(r);
    auto s2 = s1.first.split(l);
    auto st = s2.second->state;
    root = merge(merge(s2.first, s2.second), s1.second).root;
    return st;
  }
  template <typename Callable>
  state_t update(size_t k, Callable callable) {
    auto s1 = split(k);
    auto s2 = s1.second.split(1);
    s2.first.root->state = callable(s2.first.root->state);
    s2.first.root = s2.first.root->update();
    root = merge(s1.first, merge(s2.first, s2.second)).root;
    return s2.first->state;
  }

  size_t size() const { return root->size; }
  template <typename... Types>
  self_t emplace(size_t k, Types... args) {
    auto s = split(k);
    self_t rb = self_t::create(std::forward<Types>(args)...);
    root = rb.mergeL(s.first).mergeR(s.second).root;
    return *this;
  }
  template <typename... Types>
  self_t emplace_back(Types... args) {
    return emplace(root->size, std::forward<Types>(args)...);
  }
  template <typename... Types>
  self_t emplace_front(Types... args) {
    return emplace(0, std::forward<Types>(args)...);
  }
  self_t erase(size_t k) {
    auto s1 = split(k);
    auto s2 = s1.second.split(1);
    if (s2.first.root != Node::null) delete s2.first.root;
    root = merge(s1.first, s2.second).root;
    return *this;
  }
  self_t pop_back() {
    if (root->size == 0) return *this;
    return erase(root->size - 1);
  }
  self_t pop_front() {
    if (root->size == 0) return *this;
    return erase(0);
  }
  struct Node {
    static node_ptr null;
    size_t size = 1;
    node_ptr L = null, R = null;
    state_t state;

    Node() : size(0) {}
    Node(state_t &&s) : state(s) {}
    node_ptr update() {
      assert(this != null);
      size = L->size + R->size + 1;
      state.update(L->state, R->state);
      return this;
    }
    template <typename Callable>
    void traverse(Callable callable, int order = 0) const {
      if (this == null) return;
      if (order < 0) callable(state);
      L->traverse(callable, order);
      if (order == 0) callable(state);
      R->traverse(callable, order);
      if (order > 0) callable(state);
    }
  };
};
}

#define ORLIV_INIT_RBST(type)                                                  \
  template <>                                                                  \
  typename orliv::RBST<type>::Node *orliv::RBST<type>::Node::null =            \
      new typename orliv::RBST<type>::Node();

#endif
// }}}

using namespace std;

const int INF = (1ll << 31) - 1;

struct Min {
  int val, mini;
  Min() : mini(INF) {}
  Min(int v) : val(v) {}
  void update(const Min &lhs, const Min &rhs) {
    mini = min({val, lhs.mini, rhs.mini});
  }
};

ORLIV_INIT_RBST(Min);

signed main() {
  int N = in(), Q = in();

  orliv::RBST<Min> rb;
  REP(i, N) rb.emplace_back(INF);
  REP(i, Q) {
    // cout << "[";
    // rb->traverse([](const Min &m) { cout << m.val << ","; });
    // cout << "]" << endl;
    int c = in(), x = in(), y = in();
    if (c == 0) {
      rb.update(x, [y](Min &m) {
        m.val = y;
        return m;
      });
    } else {
      cout << rb.range(x, y + 1).mini << "\n";
    }
  }
  return 0;
}

Measured memory_bytes: 7920