#include <cassert>
#include <cctype>
#include <cerrno>
#include <cfloat>
#include <ciso646>
#include <climits>
#include <clocale>
#include <cmath>
#include <csetjmp>
#include <csignal>
#include <cstdarg>
#include <cstddef>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>

#include <algorithm>
#include <bitset>
#include <complex>
#include <deque>
#include <exception>
#include <fstream>
#include <functional>
#include <iomanip>
#include <ios>
#include <iosfwd>
#include <iostream>
#include <istream>
#include <iterator>
#include <limits>
#include <list>
#include <locale>
#include <map>
#include <memory>
#include <new>
#include <numeric>
#include <ostream>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <stdexcept>
#include <streambuf>
#include <string>
#include <typeinfo>
#include <utility>
#include <valarray>
#include <vector>

#include <array>
#include <atomic>
#include <chrono>
#include <condition_variable>
#include <forward_list>
#include <future>
#include <initializer_list>
#include <mutex>
#include <random>
#include <ratio>
#include <regex>
#include <system_error>
#include <thread>
#include <tuple>
#include <typeindex>
#include <type_traits>
#include <unordered_map>
#include <unordered_set>

// example:
//struct rmq {
//    using type = int;
//    static type id() {
//        return std::numeric_limits<type>::max();
//    }
//    static type op(type const& l, type const& r) {
//        return std::min(l, r);
//    }
//};

template<typename Monoid>
class segment_tree {
    using T = typename Monoid::type;

public:
    segment_tree(std::vector<T> const& init)
        : sz(init.size()),
          n(expand(init.size()))
    {
        dat.assign(n*2, Monoid::id());
        std::copy(begin(init), end(init), begin(dat) + n);
        for(int i = n - 1; i >= 0; --i) {
            dat[i] = Monoid::op(dat[i * 2], dat[i * 2 + 1]);
        }
    }

    segment_tree(int const n, T const& init = Monoid::id())
        : segment_tree(std::vector<T>(n, init))
    {}

    void update(int p, T val) {
        assert(0 <= p && p < sz);
        dat[p += n] = val;
        while(p /= 2) {
            dat[p] = Monoid::op(dat[p * 2], dat[p * 2 + 1]);
        }
    }

    // [l, r)
    T query(int l, int r) const {
        assert(0 <= l && l <= r && r <= sz);
        l += n;
        r += n;
        T res1 = Monoid::id(),
          res2 = Monoid::id();
        while(l != r) {
            if(l & 1) {
                res1 = Monoid::op(res1, dat[l++]);
            }
            if(r & 1) {
                res2 = Monoid::op(dat[--r], res2);
            }
            l /= 2;
            r /= 2;
        }
        return Monoid::op(res1, res2);
    }

    int size() const {
        return sz;
    }

private:
    int expand(int n) const {
        assert(n >= 1);
        return n == 1 ? n : expand((n + 1) / 2) * 2;
    }

private:
    const int sz;
    const int n;
    std::vector<T> dat;
};

struct rmq {
    using type = unsigned;
    static type id() { return std::numeric_limits<type>::max(); }
    static type op(type const &l, type const &r) { return std::min(l, r); }
};

using namespace std;

int main(void)
{
    int n, q;
    cin >> n >> q;
    segment_tree<rmq> st(vector<unsigned>(n, (static_cast<unsigned>(1)<<31) - 1));
    for (int i = 0; i < q; i++) {
        int com, x, y;
        cin >> com >> x >> y;
        switch (com) {
            case 0:
                st.update(x, y);
                break;
            case 1:
                std::cout << st.query(x, y+1) << std::endl;
                break;
        }
    }
    return 0;
}

Measured memory_bytes: 4112