#include <bits/stdc++.h>
using namespace std;

#define DUMP(x) cerr << #x << "=" << x << endl
#define DUMP2(x, y) cerr<<"("<<#x<<", "<<#y<<") = ("<<x<<", "<<y<<")"<< endl
#define BINARY(x) static_cast<bitset<16> >(x)

#define rep(i,n) for(int i=0;i<(int)(n);i++)
#define REP(i,m,n) for (int i=m;i<(int)(n);i++)

#define in_range(x, y, w, h) (0<=(int)(x) && (int)(x)<(int)(w) && 0<=(int)(y) && (int)(y)<(int)(h))
#define ALL(a) (a).begin(),(a).end()

typedef long long ll;
const int INF   = 1e9;
const ll  INFLL = 1e18;
typedef pair<int, int> PII;
int dx[4]={0, -1, 1, 0}, dy[4]={-1, 0, 0, 1};

#ifdef DEBUG
    #define DEBUG_FLAG 1
#else
    #define DEBUG_FLAG 0
#endif

// ????????´??°, ???????????§

/*
const int DATA_NIL = 0;
template <class T>
class SegmentTree {
private:
    const int n;
    vector<T> dat;
    void prop_to(int i) { dat[i] = max(dat[i<<1], dat[i<<1|1]); }

public:
    SegmentTree(int _n) : n(_n), dat(2*n, DATA_NIL) {}

    void fill(int l, int r, T x)
    {
        l += n, r += n;
        for (; l<r; l >>= 1, r >>= 1) {
            if (l & 1) dat[l++] += x;
            if (r & 1) dat[r-1] += x;
        }
    }

    T get(int i)
    {
        T res = dat[i += n];
        while (i >>= 1) { res += dat[i]; }
        return res;
    }

    void push()
    {
        for (int i=1; i<n; i++) {
            dat[i<<1] += dat[i];
            dat[i<<1|1] += dat[i];
            dat[i] = DATA_NIL;
        }
    }

    void dump()
    {
        cerr << "-----------" << endl;
        int h = __lg(2*n);
        for (int i=1; i<=h; i++) {
            for (int j=0; j<1<<(i-1); j++) cerr << dat[(1<<(i-1)) + j].second << " ";
            cerr << endl;
        }
        cerr << "-----------" << endl;
    }
};
*/

// ????????´??°, ???????????§
template<class Monoid>
class SegmentTree {
private:
    using T = typename Monoid::T;
    Monoid op;
    const int n;
    vector<T> dat;
    void prop_to(int i) { dat[i] = op(dat[2*i], dat[2*i+1]); }

public:
    SegmentTree(int _n) : n(_n), dat(2*_n, op.identity()) {}
    SegmentTree(const vector<T> &v) : n(v.size()), dat(2*n)
    {
        copy(v.begin(), v.end(), dat.begin() + n);
        for (int i=n-1; i>0; i--) prop_to(i);
    }

    T get(int i)
    {
        T res = dat[i += n];
        while (i >>= 1) res = op(res, dat[i]);
        return res;
    }

    void update(int l, int r, const T &x) // [l, r)
    {
        for (l += n, r += n; l < r; l >>= 1, r >>= 1) {
            if (l & 1) {dat[l] = op(dat[l], x); l++; }
            if (r & 1) {dat[r-1] = op(x, dat[r-1]); }
        }
    }
};

struct RSQ {
    using T = int;
    T operator() (const T &a, const T &b) { return a + b; }
    static constexpr T identity() { return 0; }
};


template<class T>
class SegmentTreeLazy {
private:
    const int n, h;
    const T init_dat, init_lazy;
    vector<T> dat, lazy;

    void calc(int p, int k)
    {
        if (lazy[p] == init_lazy) dat[p] = min(dat[p<<1], dat[p<<1|1]);
        else dat[p] = lazy[p];
    }

    void apply(int p, T &value, int k)
    {
        dat[p] = value;
        if (p < n) lazy[p] = value;
    }

    void build(int l, int r)
    {
        int k = 2;
        for (l += n, r += n-1; l > 1; k <<= 1) {
            l >>= 1, r >>= 1;
            for (int i = r; i >= l; i--) calc(i, k);
        }
    }

    void push(int l, int r)
    {
        int s = h, k = 1 << (h - 1);
        for (l += n, r += n-1; s > 0; s--, k >>= 1) {
            for (int i = l>>s; i <= r>>s; i++) {
                if (lazy[i] != init_lazy) {
                    apply(i<<1, lazy[i], k);
                    apply(i<<1|1, lazy[i], k);
                    lazy[i] = init_lazy;
                }
            }
        }
    }

public:
    SegmentTreeLazy(int _n) : n(_n), h(__lg(n)), init_dat(T()), init_lazy(T()), dat(2*n), lazy(2*n) {}
    SegmentTreeLazy(int _n, T _init_dat, T _init_lazy) : n(_n), h(__lg(n)), init_dat(_init_dat), 
        init_lazy(_init_lazy), dat(2*n, init_dat), lazy(2*n, init_lazy)  {}

    void modify(int l, int r, T &value)
    {
        push(l, l+1);
        push(r-1, r);

        int l0 = l, r0 = r, k = 1;
        for (l += n, r += n; l < r; l >>= 1, r >>= 1, k <<= 1) {
            if (l&1) apply(l++, value, k);
            if (r&1) apply(r-1, value, k);
        }

        build(l0, l0 + 1);
        build(r0 - 1, r0);
    }

    T query(int l, int r)
    {
        push(l, l+1);
        push(r-1, r);

        T res = init_dat;
        for (l += n, r += n; l < r; l >>= 1, r >>= 1) {
            if (l&1) res = min(dat[l++], res);
            if (r&1) res = min(res, dat[r-1]);
        }

        return res;
    }

    void dump()
    {
        cerr << "-----------" << endl;
        int hh = __lg(2*n);
        for (int i=1; i<=hh; i++) {
            for (int j=0; j<1<<(i-1); j++) {
                int idx = (1<<(i-1)) + j;
                cerr << dat[idx] << " (" << lazy[idx] << ") ";
            }
            cerr << endl;
        }
        cerr << "-----------" << endl;
    }

};

int main()
{
    ios::sync_with_stdio(false);

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

#if DEBUG_FLAG
    int n = 1;
    while (n<N) n*=2;
    SegmentTreeLazy<ll> seg_tree(n, 100, -1);
#else
    SegmentTreeLazy<ll> seg_tree(N, (1LL<<31)-1, -1);
#endif

    rep(q, Q) {
        int T; cin >> T;
        if (T == 0) {
            ll A, B, X; 
            cin >> A >> B >> X;
            seg_tree.modify(A, B+1, X);
        } else {
            int A, B;
            cin >> A >> B;
            cout << seg_tree.query(A, B+1) << endl;
        }
#if DEBUG_FLAG
        seg_tree.dump();
#endif
    }
}

Measured memory_bytes: 5972