// Original C++ solution (slower):
#include <cstdio>

#include <algorithm>

#include <climits>

using namespace std;



const int SIZE = 1 << 17; // 2^17 = 131072

template<typename T>

struct segtree {

    // ?????????????????????

    T node[2*SIZE], I;



    // ????????¬????????§??? (update, query ??? 2 ???????????????)

    T (*upd_f)(T, T), (*qry_f)(T, T);



    // ???????????¨?????????????????????????????¨?????? node ??????????????§?????????

    segtree(T (*op1)(T, T), T (*op2)(T, T), T X) {

        upd_f = op1;

        qry_f = op2;

        I = X;

        fill(node, node+2*SIZE, I);

    }



    // ??´??? idx ?????? val ????????? (upd_f ?????¨?????? update)

    void update(int idx, T val) {

        idx += SIZE - 1;

        node[idx] = upd_f(node[idx], val);

        while(idx > 0) {

            // ????????¨?????? qry_f ??????????????¨?????¨????????????

            idx = (idx - 1) / 2;

            node[idx] = qry_f(node[2*idx+1], node[2*idx+2]);

        }

    }



    // ???????????? [a, b) ?????????????????¨???????????????

    // (qry_f ?????¨????????????)

    T query(int a, int b, int l=0, int r=SIZE, int k=0) {

        if(b <= l || r <= a) return I;

        if(a <= l && r <= b) return node[k];

        int mid = (l + r) / 2;

        T vl = query(a, b, l, mid, 2*k+1);

        T vr = query(a, b, mid, r, 2*k+2);

        return qry_f(vl, vr);

    }

};



int upd(int a, int b) {return b;}

int fnd(int a, int b) {return min(a, b);}

int main() {

    segtree<int> seg(upd, fnd, INT_MAX);

    int N, Q; scanf("%d%d", &N, &Q);

    for(int i=0; i<Q; i++) {

        int c, x, y; scanf("%d%d%d", &c, &x, &y);

        if(c == 0) seg.update(x, y);

        else printf("%d\n", seg.query(x, y+1));

    }

    return 0;

}

// Optimized solution to the same problem (faster):
#include <iostream>

#include <cstdio>

#include <vector>

#include <algorithm>

#include <cstdlib>

#include <functional>

#include <climits>

using namespace std;



// 動的セグメント木 (必要なノードだけ作る)



template <typename MonoidType>

struct SegNode {

    MonoidType value;

    SegNode *ch[2];

    SegNode() {}

    SegNode(MonoidType value_) : value(value_) {

        ch[0] = ch[1] = nullptr;

    }

};



template <typename MonoidType, typename IdxType = int>

struct DynamicSegmentTree {

    using Function = function< MonoidType(MonoidType, MonoidType) >;



    // node, identity element

    IdxType n;

    SegNode<MonoidType>* root;

    MonoidType E0;



    // update / combine function

    Function upd_f, cmb_f;



    // initialize

    DynamicSegmentTree() {

        root = new SegNode<MonoidType>;

    }

    DynamicSegmentTree(IdxType n_, MonoidType E0_,

                       Function upd_f_, Function cmb_f_) :

        E0(E0_), upd_f(upd_f_), cmb_f(cmb_f_) {

        root = new SegNode<MonoidType>(E0_);

        n = 1; while(n < n_) n *= 2;

    }



    void update(SegNode<MonoidType> *node, IdxType k, MonoidType x, IdxType l, IdxType r) {

        if(r - l == 1) {

            node->value = upd_f(node->value, x);

            return;

        }



        IdxType mid = (l + r) / 2;

        MonoidType vl = E0, vr = E0;

        if(l <= k and k < mid) {

            if(!node->ch[0]) node->ch[0] = new SegNode<MonoidType>(E0);

            update(node->ch[0], k, x, l, mid);

        }

        if(mid <= k and k < r) {

            if(!node->ch[1]) node->ch[1] = new SegNode<MonoidType>(E0);

            update(node->ch[1], k, x, mid, r);

        }

        vl = (node->ch[0] ? node->ch[0]->value : E0);

        vr = (node->ch[1] ? node->ch[1]->value : E0);

        node->value = cmb_f(vl, vr);

    }



    MonoidType query(SegNode<MonoidType> *node, IdxType a, IdxType b, IdxType l, IdxType r) {

        if(b <= l or r <= a) return E0;

        if(a <= l and r <= b) return node->value;



        IdxType mid = (l + r) / 2;

        MonoidType vl = (node->ch[0] ? query(node->ch[0], a, b, l, mid) : E0);

        MonoidType vr = (node->ch[1] ? query(node->ch[1], a, b, mid, r) : E0);

        return cmb_f(vl, vr);

    }

    

    // update k-th element (applied value: x)

    void update(IdxType k, MonoidType x) {

        update(root, k, x, 0, n);

    }



    // range query for [a, b)

    MonoidType query(IdxType a, IdxType b) {

        return query(root, a, b, 0, n);

    }

};



void DSL_2_A() {

    int N, Q; cin >> N >> Q;

    int indexed = 0;



    DynamicSegmentTree<int> seg(N, INT_MAX,

                                [](int a, int b) { return b; },

                                [](int a, int b) { return min(a, b); });

    for(int i=0; i<Q; i++) {

        int q, x, y; cin >> q >> x >> y;

        if(q == 0) {

            x -= indexed;

            seg.update(x, y);

        }

        if(q == 1) {

            x -= indexed; y -= indexed; y++;

            cout << seg.query(x, y) << endl;

        }

    }

}



int main() {

    DSL_2_A();

    return 0;

}




// Fastest known solution for this problem: