#include <bits/stdc++.h>
#define REP(i,n) for (long long i=0;i<(n);i++)
#define FOR(i,a,b) for (long long i=(a);i<(b);i++)
#define RREP(i,n) for(long long i=n;i>=0;i--)
#define RFOR(i,a,b) for(long long i=(a);i>(b);i--)
#define dump1d_arr(array) REP(i,array.size()) cerr << #array << "[" << (i) << "] ==> " << (array[i]) << endl;
#define dump2d_arr(array) REP(i,array.size()) REP(j,array[i].size()) cerr << #array << "[" << (i) << "]" << "[" << (j) << "] ==> " << (array[i][j]) << endl;
#define dump(x)  cerr << #x << " => " << (x) << endl;
#define dumpP(p) cerr << "( " << p.first << " , " << p.second << " )" << ends;
#define CLR(vec) { REP(i,vec.size()) vec[i] = 0; } 
#define SORT(c) sort((c).begin(),(c).end())
#define MIN(vec) *min_element(vec.begin(), vec.end());
#define MAX(vec) *max_element(vec.begin(), vec.end());
#define UNIQ(vec) vec.erase(unique(vec.begin(), vec.end()),vec.end());
#define IN(n,m)  (!(m.find(n) == m.end()))
#define ENUM(m) for (auto itr = m.begin(); itr != m.end(); ++itr)
#define dump_MAP(m) for(auto itr = m.begin(); itr != m.end(); ++itr) { cerr << itr->first << " --> "  << itr->second << endl; }
#define FINDL(vec,x) (lower_bound(vec.begin(),vec.end(),x) - vec.begin())
#define FINDU(vec,x) (upper_bound(vec.begin(),vec.end(),x) - vec.begin())
#define ROUND(N) setprecision(N)
#define ROUND_PRINT(N,val) cout << fixed;cout << setprecision(N) << val << endl
using namespace std;
template <class Monoid,class MonoidAct>
class LazySegmentTree {
private:
    typedef tuple<int,int,int> tp;
    using T1 = typename Monoid::T;
    using T2 = typename MonoidAct::T;
    static T1 op2(const T1& l,const T2& r) { return r != MonoidAct::id() ? r : l;}
    vector<T1> data;
    vector<T2> lazy;
    const int h, n;

private:
    void eval(int node) {
        if (lazy[node] == MonoidAct::id()) return;
        if (node < n) {
            lazy[node * 2] = MonoidAct::op3(lazy[node * 2], lazy[node]);
            lazy[node * 2 + 1] = MonoidAct::op3(lazy[node * 2 + 1], lazy[node]);
        }
        data[node] = op2(data[node], lazy[node]);
        lazy[node] = MonoidAct::id();
    }
    void update(int node) {
        data[node] = Monoid::op1(op2(data[node * 2], lazy[node * 2])
                        ,op2(data[node * 2 + 1], lazy[node * 2 + 1]));
    }

public:
    LazySegmentTree(int n_)
        : h(ceil(log2(n_))), n(1 << h) {data.resize(n * 2, Monoid::id());lazy.resize(n * 2, MonoidAct::id());}
    LazySegmentTree(int n_, T1 v1)
        : h(ceil(log2(n_))), n(1 << h) {data.resize(n * 2, v1);lazy.resize(n * 2, MonoidAct::id());}
    LazySegmentTree(const vector<T1>& data_)
        : h(ceil(log2(data_.size()))), n(1 << h) {
            data.resize(n * 2,Monoid::id());
            lazy.resize(n * 2, MonoidAct::id());
            init(data_);
    }
    void init() {
        for (int i = n - 1; i >= 1; i--) data[i] = Monoid::op1(data[i * 2], data[i * 2 + 1]);
    }
    void init(const vector<T1>& data_) {
        for (int i = 0; i < (int)data_.size(); i++) data[i + n] = data_[i];
        init();
    }
    void update(int l, int r, T2 val) {
        int lb,ub,node,bound;
        vector<int> par;
        stack<tp> st;
        st.push(make_tuple(1,0,n));
        while (!st.empty()) {
            tp cur = st.top();st.pop();
            lb = get<1>(cur);ub = get<2>(cur);node = get<0>(cur);
            if (ub <= l || r <= lb) continue;
            if (l <= lb && ub <= r) lazy[node] = MonoidAct::op3(lazy[node],val);
            else {
                par.push_back(node);
                eval(node);
                bound = (lb+ub)/2;
                st.push(make_tuple(node*2,lb,bound));
                st.push(make_tuple(node*2+1,bound,ub));
            }
        }
        for (int i = par.size()-1;i >= 0;i--) {
            data[par[i]] = Monoid::op1(op2(data[par[i] * 2], lazy[par[i] * 2])
                        ,op2(data[par[i] * 2 + 1], lazy[par[i] * 2 + 1]));
        }
    }

    T1 find(int l, int r) {
        T1 ret = Monoid::id();
        int lb,ub,node,bound;
        stack<tp> st;
        st.push(make_tuple(1,0,n));
        while (!st.empty()) {
            tp cur = st.top();st.pop();
            lb = get<1>(cur);ub = get<2>(cur);node = get<0>(cur);
            if (ub <= l || r <= lb) continue;
            if (l <= lb && ub <= r) ret = Monoid::op1(ret,op2(data[node],lazy[node]));
            else {
                eval(node);
                bound = (lb+ub)/2;
                st.push(make_tuple(node*2,lb,bound));
                st.push(make_tuple(node*2+1,bound,ub));
            }
        }
        return ret;
    }
};


struct RMQ {
    using T = int;
    static T op1(const T& a, const T& b) { return min(a, b); }
    static constexpr T id() {return numeric_limits<T>::max(); }
};

struct RUQ {
    using T = int;
    static T op3(const T& l,const T& r) { return r != id() ? r : l;}
    static constexpr T id() { return (-1); }
};

int main(void) {
    int n,q,com,s,t,x;
    cin >> n >> q;
    vector<int> a(n,numeric_limits<int>::max());
    LazySegmentTree<RMQ,RUQ> sg(a);
    REP(i,q) {
        cin >> com;
        if (!com) {
            cin >> s >> t >> x;
            sg.update(s,t+1,x);
        }
        else {
            cin >> s >> t;
            cout << sg.find(s,t+1) << endl;
        }
    }
}



Measured memory_bytes: 5440