#include <algorithm>
#include <bitset>
#include <cmath>
#include <deque>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <utility>
#include <vector>
using ll = long long;
#define rep(i, n) for (int i = 0; i < n; i++)
#define repk(i, k, n) for (int i = k; i < n; i++)
#define MOD 1000000007
#define INF 1e9
#define PIE 3.14159265358979323

template <class T>
inline bool chmin(T &a, T b) {
    if (a > b) {
        a = b;
        return true;
    }
    return false;
}
template <class T>
inline bool chmax(T &a, T b) {
    if (a < b) {
        a = b;
        return true;
    }
    return false;
}
template <class T>
T GCD(T a, T b) {
    if (b == 0)
        return a;
    else
        return GCD(b, a % b);
}
template <class T>
inline T LCM(T a, T b) {
    return (a * b) / GCD(a, b);
}

using namespace std;
//#inculude <bits/stdc++.h>
//#define int long long

template <class T>
class SegmentTree {
  private:
    int n = 1;
    vector<T> segtree;
    function<T(T, T)> operation;
    T ie;

    T _query(int a, int b, int k, int l, int r) {
        if (a >= r || b <= l)
            return ie;
        else if (a <= l && b >= r)
            return segtree[k];
        else {
            int vl = _query(a, b, 2 * k + 1, l, (l + r) / 2);
            int vr = _query(a, b, 2 * k + 2, (l + r) / 2, r);
            return operation(vl, vr);
        }
    }

  public:
    SegmentTree(vector<T> v, function<T(T, T)> _operation, T _ie)
        : operation(_operation), ie(_ie) {
        while (v.size() > n)
            n *= 2;
        segtree.resize(2 * n - 1, ie);
        for (int i = 0; i < v.size(); i++)
            segtree[i + n - 1] = v[i];
        for (int i = n - 2; i >= 0; i--)
            segtree[i] = operation(segtree[2 * i + 1], segtree[2 * i + 2]);
    }

    T operator[](int i) {
        return segtree[i + n - 1];
    }

    void update(int i, T x) {
        i += n - 1;
        segtree[i] = x;
        while (i > 0) {
            i = (i - 1) / 2;
            segtree[i] = operation(segtree[2 * i + 1], segtree[2 * i + 2]);
        }
    }

    T query(int a, int b) {
        return _query(a, b, 0, 0, n);
    }
};

/*
  抽象遅延伝播Segment Tree
*/

template <class T, class M>
class LazySegmentTree {
  private:
    int n = 1;
    vector<T> segtree;
    vector<T> lazy;
    function<T(T, T)> operation;
    function<M(M, M)> action_to_action;
    function<T(T, M)> action;
    T t_ie;
    M m_ie;

    void eval(int k) {
        if (lazy[k] == m_ie)
            return;
        if (k < n - 1) {
            lazy[2 * k + 1] = action_to_action(lazy[2 * k + 1], lazy[k]);
            lazy[2 * k + 2] = action_to_action(lazy[2 * k + 2], lazy[k]);
        }
        segtree[k] = action(segtree[k], lazy[k]);
        lazy[k] = m_ie;
    }

    void _update(int a, int b, T x, int k, int l, int r) {
        eval(k);
        if (a >= r || l >= b)
            return;
        else if (a <= l && r <= b) {
            lazy[k] = action_to_action(lazy[k], x);
            eval(k);
        }
        else {
            _update(a, b, x, 2 * k + 1, l, (l + r) / 2);
            _update(a, b, x, 2 * k + 2, (l + r) / 2, r);
            segtree[k] = operation(segtree[2 * k + 1], segtree[2 * k + 2]);
        }
    }

    T _query(int a, int b, int k, int l, int r) {
        eval(k);
        if (a >= r || b <= l)
            return t_ie;
        else if (a <= l && b >= r)
            return segtree[k];
        else {
            int vl = _query(a, b, 2 * k + 1, l, (l + r) / 2);
            int vr = _query(a, b, 2 * k + 2, (l + r) / 2, r);
            return operation(vl, vr);
        }
    }

  public:
    LazySegmentTree(vector<T> v, function<T(T, T)> _operation,
                    function<M(M, M)> _action_to_action,
                    function<T(T, M)> _action, T _t_ie, M _m_ie)
        : operation(_operation), action_to_action(_action_to_action),
          action(_action), t_ie(_t_ie), m_ie(_m_ie) {
        while (v.size() > n)
            n *= 2;
        segtree.resize(2 * n - 1, t_ie);
        lazy.resize(2 * n - 1, m_ie);
        for (int i = 0; i < v.size(); i++)
            segtree[i + n - 1] = v[i];
        for (int i = n - 2; i >= 0; i--)
            segtree[i] = operation(segtree[2 * i + 1], segtree[2 * i + 2]);
    }

    void update(int a, int b, T x) {
        _update(a, b, x, 0, 0, n);
    }

    T query(int a, int b) {
        return _query(a, b, 0, 0, n);
    }
};

signed main() {
    int n, q, com, x, y, z;
    cin >> n >> q;
    vector<int> v(n, INT32_MAX);
    auto fx = [](int a, int b) -> int { return min(a, b); };
    auto fa = [](int a, int b) -> int { return b; };
    auto fm = [](int a, int b) -> int { return b; };
    int t_ie = INT32_MAX;
    int m_ie = INT32_MAX;
    LazySegmentTree<int, int> seg(v, fx, fa, fm, t_ie, m_ie);
    rep(i, q) {
        cin >> com >> x >> y;
        if (com == 0) {
            cin >> z;
            seg.update(x, y + 1, z);
        }
        else
            cout << seg.query(x, y + 1) << endl;
    }
    return 0;
}


Measured memory_bytes: 5728