#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <utility>
#include <tuple>
#include <queue>
#include <deque>
#include <map>
#include <set>
#include <cmath>
#include <iomanip>
#include <cassert>
#define REP(i, n) for (int i = 0; i < (n); ++i)
#define ALL(x) (x).begin(), (x).end()
#define SZ(x) (int)(x).size()
using namespace std;
using ll = long long;
constexpr ll INF = 3000000000000000000;

template <typename Operator>
struct LazySegmentTree {
    Operator OP;
    using NodeType = decltype(OP.NodeE);
    using FuncType = decltype(OP.FuncE);
    int length, height;
    vector<NodeType> node;
    vector<FuncType> lazy;
    vector<int> width;
    LazySegmentTree(int n) {
        length = 1;
        height = 0;
        while (length < n) {
            length <<= 1;
            ++height;
        }
        node.resize(length << 1, OP.NodeE);
        lazy.resize(length << 1, OP.FuncE);
        width.resize(length << 1, 1);
        for (int i = length - 1; i > 0; --i) width[i] = width[i << 1] << 1;
    }
    LazySegmentTree(vector<NodeType> &vec) {
        length = 1;
        height = 0;
        while (length < SZ(vec)) {
            length <<= 1;
            ++height;
        }
        node.resize(length << 1, OP.NodeE);
        REP(i, SZ(vec)) node[i + length] = vec[i];
        for (int i = length - 1; i > 0; --i) node[i] = OP.MergeNode(node[(i << 1) | 0], node[(i << 1) | 1]);
        lazy.resize(length << 1, OP.FuncE);
        width.resize(length << 1, 1);
        for (int i = length - 1; i > 0; --i) width[i] = width[i << 1] << 1;
    }
    void eval(int n) {
        node[n] = OP.NodeFunc(node[n], lazy[n], width[n]);
        if (n < length) {
            lazy[(n << 1) | 0] = OP.MergeFunc(lazy[(n << 1) | 0], lazy[n]);
            lazy[(n << 1) | 1] = OP.MergeFunc(lazy[(n << 1) | 1], lazy[n]);
        }
        lazy[n] = OP.FuncE;
    }
    void update(int a, int b, FuncType x) {
        int l = a + length, r = b + length - 1;
        for (int i = height; i > 0; --i) {
            eval(l >> i);
            eval(r >> i);
        }
        ++r;
        while (r > l) {
            if (l & 1) {
                lazy[l] = OP.MergeFunc(lazy[l], x);
                eval(l);
                ++l;
            }
            if (r & 1) {
                --r;
                lazy[r] = OP.MergeFunc(lazy[r], x);
                eval(r);
            }
            l >>= 1; r >>= 1;
        }
        l = a + length; r = b + length - 1;
        while (l >>= 1) node[l] = OP.MergeNode(OP.NodeFunc(node[(l << 1) | 0], lazy[(l << 1) | 0], width[(l << 1) | 0]), OP.NodeFunc(node[(l << 1) | 1], lazy[(l << 1) | 1], width[(l << 1) | 1]));
        while (r >>= 1) node[r] = OP.MergeNode(OP.NodeFunc(node[(r << 1) | 0], lazy[(r << 1) | 0], width[(r << 1) | 0]), OP.NodeFunc(node[(r << 1) | 1], lazy[(r << 1) | 1], width[(r << 1) | 1]));
    }
    NodeType get(int a, int b) {
        int l = a + length, r = b + length - 1;
        for (int i = height; i >= 0; --i) {
            eval(l >> i);
            eval(r >> i);
        }
        ++r;
        NodeType vl = OP.NodeE, vr = OP.NodeE;
        while (l < r) {
            if (l & 1) {
                vl = OP.MergeNode(vl, OP.NodeFunc(node[l], lazy[l], width[l]));
                ++l;
            }
            if (r & 1) {
                --r;
                vr = OP.MergeNode(OP.NodeFunc(node[r], lazy[r], width[r]), vr);
            }
            l >>= 1; r >>= 1;
        }
        return OP.MergeNode(vl, vr);
    }
};

struct hoge {
    ll NodeE = INF;
    ll FuncE = INF;
    ll MergeNode(ll x, ll y) {
        return min(x, y);
    }
    ll MergeFunc(ll x, ll y) {
        if (y == INF) return x;
        else return y;
    }
    ll NodeFunc(ll x, ll y, int len) {
        if (y == INF) return x;
        else return y;
    }
};

int main() {
    int n, q;
    cin >> n >> q;
    LazySegmentTree<hoge> LST(n);
    LST.update(0, n, (1LL << 31) - 1);
    REP(_, q) {
        int num;
        cin >> num;
        if (!num) {
            int s, t, x;
            cin >> s >> t >> x;
            ++t;
            LST.update(s, t, x);
        } else {
            int s, t;
            cin >> s >> t;
            ++t;
            cout << LST.get(s, t) << "\n";
        }
    }
    
    return 0;
}



Measured memory_bytes: 7772