#pragma region Macro
#pragma region Basic
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<vi> vvi;
typedef vector<vl> vvl;
#define REP(i, n) for (int i = 0, i##_len = (n); i < i##_len; ++i)
#define FOR(i, a, b) for (int i = (a), i##_len = (b); i < i##_len; i++)
#define FORD(i, a, b) for (int i = (a), i##_len = (b); i > i##_len; i--)
#define FORR(t, a) for (auto t : a)
#define ALL(x) (x).begin(), (x).end()  // sortなどの引数を省略したい
#define GET(i, j) get<j>(i)
#define MT(x, ...) make_tuple(x, __VA_ARGS__)
#define SZ(x) ((int)(x).size())
#define ZERO(x) memset(x, 0, sizeof(x))
#define FILL(x, y) memset(x, y, sizeof(x))
#define PB push_back
#define EB emplace_back
#ifdef _DEBUG
#define PRE_COMMAND             \
    std::cin.rdbuf(in.rdbuf()); \
    cout << fixed << setprecision(15);
#else
#define PRE_COMMAND cout << fixed << setprecision(15);
#endif
const double EPS = 1e-10;
const double PI = acos(-1.0);
template <class T>
auto MAX(T& seq) {
    return *max_element(seq.begin(), seq.end());
}
template <class T>
auto MIN(T& seq) {
    return *min_element(seq.begin(), seq.end());
}
template <class T>
auto SUM(T& seq) {
    T temp{0};
    auto& temp2 = temp[0];
    return accumulate(seq.begin(), seq.end(), temp2);
}
template <class T>
void SORT(T& seq) {
    sort(seq.begin(), seq.end());
}
template <class T, class S>
void SORT(T& seq, S& sort_order) {
    sort(seq.begin(), seq.end(), sort_order);
}
template <class T>
void SORTR(vector<T>& seq) {
    sort(seq.begin(), seq.end(), greater<T>());
}
template <class T>
void CHMAX(T& a, const T& b) {
    if (a < b) { a = b; }
}
template <class T>
void CHMIN(T& a, const T& b) {
    if (b < a) { a = b; }
}
template <class T>
set<T> VECTOR_2_SET(vector<T>& v) {
    set<T> s;
    for (auto ele : v) { s.insert(ele); }
    return s;
}
template <class T>
vector<T> SET_2_VECTOR(set<T>& s) {
    vector<T> v;
    for (auto ele : s) { v.push_back(ele); }
    return v;
}
#pragma endregion Basic
#pragma region overload
template <class T, class S>
void operator+=(vector<T>& l, S& r) {
    for (auto i : r) { l.push_back(i); }
}
template <class T, class S>
void operator+=(set<T>& l, S& r) {
    for (auto i : r) { l.insert(i); }
}
template <class T, class S>
void operator+=(multiset<T>& l, S& r) {
    for (auto i : r) { l.insert(i); }
}
template <class T, class S>
vector<T> operator+(vector<T>& l, S& r) {
    vector<T> l_copy = l;
    for (auto i : r) { l_copy.push_back(i); }
    return l_copy;
}
template <class T>
vector<T> operator+(const vector<T> l, const vector<T>& r) {
    vector<T> l_copy = l;
    for (auto i : r) { l_copy.push_back(i); }
    return l_copy;
}
template <class T, class S>
set<T> operator+(set<T>& l, S& r) {
    set<T> l_copy = l;
    for (auto i : r) { l_copy.insert(i); }
    return l_copy;
}
template <class T>
set<T> operator+(const set<T> l, const set<T>& r) {
    set<T> l_copy = l;
    for (auto i : r) { l_copy.insert(i); }
    return l_copy;
}
template <class T, class S>
multiset<T> operator+(multiset<T>& l, S& r) {
    set<T> l_copy = l;
    for (auto i : r) { l_copy.insert(i); }
    return l_copy;
}
template <class T>
multiset<T> operator+(const multiset<T> l, const set<T>& r) {
    set<T> l_copy = l;
    for (auto i : r) { l_copy.insert(i); }
    return l_copy;
}
string operator+(const string l, const string& r) {
    string str = l;
    str += r;
    return str;
}
string operator*(const string l, const size_t& r) {
    string str = l;
    for (size_t i = 0; i < r; i++) { str += l; }
    return str;
}
#pragma endregion overload
#pragma region Input
template <class Head>
void INPUT(vector<Head>& head);
template <size_t N, class Head>
void INPUT(array<Head, N>& head);
template <class T1>
void INPUT(tuple<T1>& t);
template <class T1, class T2>
void INPUT(tuple<T1, T2>& t);
template <class T1, class T2, class T3>
void INPUT(tuple<T1, T2, T3>& t);
template <class T1, class T2, class T3, class T4>
void INPUT(tuple<T1, T2, T3, T4>& t);
template <class T1, class T2, class T3, class T4, class T5>
void INPUT(tuple<T1, T2, T3, T4, T5>& t);
template <class Head>
void INPUT(Head& head);
template <class Head, class... Tail>
void INPUT(Head& head, Tail&... tail);
//本体
template <class Head>
void INPUT(vector<Head>& head) {
    for (size_t i = 0; i < head.size(); i++) { INPUT(head[i]); }
}
template <size_t N, class Head>
void INPUT(array<Head, N>& head) {
    for (size_t i = 0; i < head.size(); i++) { INPUT(head[i]); }
}
template <class T1>
void INPUT(tuple<T1>& t) {
    cin >> get<0>(t);
}
template <class T1, class T2>
void INPUT(tuple<T1, T2>& t) {
    cin >> get<0>(t) >> get<1>(t);
}
template <class T1, class T2, class T3>
void INPUT(tuple<T1, T2, T3>& t) {
    cin >> get<0>(t) >> get<1>(t) >> get<2>(t);
}
template <class T1, class T2, class T3, class T4>
void INPUT(tuple<T1, T2, T3, T4>& t) {
    cin >> get<0>(t) >> get<1>(t) >> get<2>(t) >> get<3>(t);
}
template <class T1, class T2, class T3, class T4, class T5>
void INPUT(tuple<T1, T2, T3, T4, T5>& t) {
    cin >> get<0>(t) >> get<1>(t) >> get<2>(t) >> get<3>(t) >> get<4>(t);
}
template <class Head>
void INPUT(Head& head) {
    cin >> head;
}
template <class Head, class... Tail>
void INPUT(Head& head, Tail&... tail) {
    INPUT(head);
    INPUT((tail)...);
}
#pragma endregion Input
#pragma region Print
template <class T1>
void PRINT2(tuple<T1> t);
template <class T1, class T2>
void PRINT2(tuple<T1, T2> t);
template <class T1, class T2, class T3>
void PRINT2(tuple<T1, T2, T3> t);
template <class T1, class T2, class T3, class T4>
void PRINT2(tuple<T1, T2, T3, T4> t);
template <class T1, class T2, class T3, class T4, class T5>
void PRINT2(tuple<T1, T2, T3, T4, T5> t);
template <class Head>
void PRINT2(vector<Head> head);
template <class Head>
void PRINT2(vector<vector<Head>> head);
template <size_t N, class Head>
void PRINT2(vector<array<Head, N>> head);
template <class... Head>
void PRINT2(vector<tuple<Head...>> head);
template <size_t N, class Head>
void PRINT2(array<Head, N> head);
template <class Head>
void PRINT2(Head head);
template <class Head, class... Tail>
void PRINT2(Head head, Tail... tail);
template <class Head>
void PRINT(Head head);
template <class... Head>
void PRINT(Head... head);
template <int N, class Head>
void PRINT(Head head);
template <class T1>
void PRINT2(tuple<T1> t) {
    PRINT2(get<0>(t));
}
template <class T1, class T2>
void PRINT2(tuple<T1, T2> t) {
    PRINT2(get<0>(t), get<1>(t));
}
template <class T1, class T2, class T3>
void PRINT2(tuple<T1, T2, T3> t) {
    PRINT2(get<0>(t), get<1>(t), get<2>(t));
}
template <class T1, class T2, class T3, class T4>
void PRINT2(tuple<T1, T2, T3, T4> t) {
    PRINT2(get<0>(t), get<1>(t), get<2>(t), get<3>(t));
}
template <class T1, class T2, class T3, class T4, class T5>
void PRINT2(tuple<T1, T2, T3, T4, T5> t) {
    PRINT2(get<0>(t), get<1>(t), get<2>(t), get<3>(t), get<4>(t));
}
template <class Head>
void PRINT2(vector<Head> head) {
    for (auto i = head.begin(); i != head.end(); i++) {
        PRINT2(*i);
        if (i != head.end() - 1) { cout << " "; }
    }
}
template <class Head>
void PRINT2(vector<vector<Head>> head) {
    for (auto i = head.begin(); i != head.end(); i++) {
        PRINT2(*i);
        if (i != head.end() - 1) { cout << endl; }
    }
}
template <size_t N, class Head>
void PRINT2(vector<array<Head, N>> head) {
    for (auto i = head.begin(); i != head.end(); i++) {
        PRINT2(*i);
        if (i != head.end() - 1) { cout << endl; }
    }
}
template <class... Head>
void PRINT2(vector<tuple<Head...>> head) {
    for (auto i = head.begin(); i != head.end(); i++) {
        PRINT2(*i);
        if (i != head.end() - 1) { cout << endl; }
    }
}
template <size_t N, class Head>
void PRINT2(array<Head, N> head) {
    for (auto i = head.begin(); i != head.end(); i++) {
        PRINT2(*i);
        if (i != head.end() - 1) { cout << " "; }
    }
}
template <class Head>
void PRINT2(Head head) {
    cout << head;
}
template <class Head, class... Tail>
void PRINT2(Head head, Tail... tail) {
    PRINT2(head);
    cout << " ";
    PRINT2((tail)...);
}
template <class Head>
void PRINT(Head head) {
    PRINT2(head);
    cout << endl;
}
template <class... Head>
void PRINT(Head... head) {
    PRINT2((head)...);
    cout << endl;
}
template <int N, class Head>
void PRINT(Head head) {
    PRINT2(head);
    cout << endl;
}
#pragma endregion Print
#pragma endregion Macro

// ini：上限（下限）,base：元の配列,monoid：モノイド,tree：セグ木,depth：treeの深さ,
// basesize：baseの要素数,treesize：treeの要素数,num：treesize-basesize
// 初期値（上限とか下限）を決定
template <class num_type>
struct segtree {
    int num, depth, basesize, treesize;
    vector<num_type> base, tree;
    using func_type = num_type(num_type&, num_type&);
    num_type (*monoid)(num_type& a, num_type& b);
    map<num_type, int> size_map;
    num_type ini;
    // 元の配列, モノイド, 初期値
    segtree(vector<num_type> tmp1, func_type tmp2, num_type tmp3)
        : base(tmp1), monoid(tmp2), ini(tmp3) {
        basesize = (int)base.size();
        num = 1;
        depth = 1;
        while (num < basesize) {
            num *= 2;
            depth++;
        }
        tmp3 = num;
        int tmp4 = 1;
        while (tmp3 > 0) {
            size_map[tmp3] = tmp4 - 1;
            tmp3 /= 2;
            tmp4 *= 2;
        }
        num--;
        treesize = num * 2 + 1;
        tree.assign(treesize, ini);
        for (int i = num; i < num + basesize; i++) { tree[i] = base[i - num]; }
        for (int i = num + basesize; i < treesize; i++) { tree[i] = ini; }
        for (int i = num - 1; i > -1; i--) {
            tree[i] = monoid(tree[2 * i + 1], tree[2 * i + 2]);
        }
    }
    // 条件を満たす(サンプルの条件はs以下になること)最大のインデックスを返す関数
    template <class func_type2>
    int max_index(func_type2 index_func) {
        int i = 0;
        while (i < num) {
            int k = 2 * i + 1;
            if (index_func(tree[k + 1])) {
                i = k + 1;
                continue;
            }
            if (index_func(tree[k])) {
                i = k;
                continue;
            }
            return -1;
        }
        return i - num;
    }
    template <class func_type2>
    int min_index(func_type2 index_func) {
        int i = 0;
        while (i < num) {
            int k = 2 * i + 1;
            if (index_func(tree[k])) {
                i = k;
                continue;
            }
            if (index_func(tree[k + 1])) {
                i = k + 1;
                continue;
            }
            return -1;
        }
        return i - num;
    }

    // 半開区間[lower,upper)の最小値（とか）を探す関数
    num_type search(int lower, int upper) {
        num_type ret = ini;
        vector<pair<int, int>> stack(1, make_pair(0, num + 1));
        vector<num_type>* tree_local = &tree;
        map<num_type, int>* size_map_local = &size_map;
        // func_type monoid_local = monoid;
        int l, r, m, s = 1;
        while (s) {
            tie(l, r) = stack.back();
            stack.pop_back();
            if (lower <= l && r <= upper) {
                ret = min(
                    ret,
                    (*tree_local)[(*size_map_local)[(r - l)] + l / (r - l)]);
                s--;
            } else {
                m = (l + r) / 2;
                if (upper <= m) {
                    stack.push_back({l, m});
                } else if (m <= lower) {
                    stack.push_back({m, r});
                } else {
                    stack.push_back({l, m});
                    stack.push_back({m, r});
                    s++;
                }
            }
        }
        return ret;
    }

    // base[i]をsに更新してセグ木全体を更新する関数
    void update(int index, num_type new_value) {
        int i = index + num;
        tree[i] = new_value;
        while (i) {
            i = (i - 1) / 2;
            num_type temp = monoid(tree[2 * i + 1], tree[2 * i + 2]);
            if (tree[i] != temp) {
                tree[i] = temp;
                continue;
            }
            break;
        }
    }

    // 和がw以上となる最小のインデックスを求める
    int lowerbound(num_type w) {
        if (w <= 0) { return 0; }
        if (w > tree[0]) { return basesize; }
        int x = 0;
        for (int i = 0; i < depth - 1; i++) {
            if (tree[2 * x + 1] < w) {
                w -= tree[2 * x + 1];
                x = 2 * x + 2;
            } else {
                x = 2 * x + 1;
            }
        }
        return x - num;
    }
};

int main() {
    PRE_COMMAND
    int n, m;
    INPUT(n, m);

    ll ini = (ll)(pow(2, 31) - 1);
    vector<ll> iniv(n, ini);
    segtree<ll> seg(
        iniv, [](ll& a, ll& b) { return min(a, b); }, ini);
    ll c, x, y;
    for (int i = 0; i < m; i++) {
        INPUT(c, x, y);
        if (c == 0) {
            seg.update((int)x, y);
        } else {
            PRINT(seg.search((int)x, (int)y + 1));
        }
    }
}



Measured memory_bytes: 7292