#include <cassert>
#include <cctype>
#include <cerrno>
#include <cfloat>
#include <ciso646>
#include <climits>
#include <clocale>
#include <cmath>
#include <csetjmp>
#include <csignal>
#include <cstdarg>
#include <cstddef>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <cwchar>
#include <cwctype>
#include <ccomplex>
#include <cfenv>
#include <cinttypes>
#include <cstdbool>
#include <cstdint>
#include <ctgmath>
#include <algorithm>
#include <bitset>
#include <complex>
#include <deque>
#include <exception>
#include <fstream>
#include <functional>
#include <iomanip>
#include <ios>
#include <iosfwd>
#include <iostream>
#include <istream>
#include <iterator>
#include <limits>
#include <list>
#include <locale>
#include <map>
#include <memory>
#include <new>
#include <numeric>
#include <ostream>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <stdexcept>
#include <streambuf>
#include <string>
#include <typeinfo>
#include <utility>
#include <valarray>
#include <vector>
#include <array>
#include <atomic>
#include <chrono>
#include <codecvt>
#include <condition_variable>
#include <forward_list>
#include <future>
#include <initializer_list>
#include <mutex>
#include <random>
#include <ratio>
#include <regex>
#include <scoped_allocator>
#include <system_error>
#include <thread>
#include <tuple>
#include <typeindex>
#include <type_traits>
#include <unordered_map>
#include <unordered_set>
#include <shared_mutex>

#ifdef DEBUG
#include "libs/debug.cpp"
#define DEBUG 1
#else
#define DEBUG 0
#endif

#define rep(i, n) repr((i), 0, (n))
#define repr(i, a, t) reps((i), (a), (t), 1)
#define reps(i, a, t, s) for (long long (i) = (a); (i) < (long long)(t); (i) += (s))
#define rrep(i, n) rrepr((i), (n), 0)
#define rrepr(i, a, t) rreps((i), (a), (t), 1)
#define rreps(i, a, t, s) for (long long (i) = (a) - 1; (i) >= (long long)(t); (i) -= (s))
#define each(v, c) for (auto &&(v) : (c))
#define all(c) (c).begin(), (c).end()

using namespace std;

// コンテナのメンバ関数を使わないと O(N) おぼえたらけす
template<typename T>
typename set<T>::iterator lower_bound(typename set<T>::iterator l, typename set<T>::iterator r, const T &v);
template<typename T>
typename set<T>::iterator upper_bound(typename set<T>::iterator l, typename set<T>::iterator r, const T &v);
template<typename S, typename T>
typename map<S, T>::iterator lower_bound(typename map<S, T>::iterator l, typename map<S, T>::iterator r, const T &v);
template<typename S, typename T>
typename map<S, T>::iterator upper_bound(typename map<S, T>::iterator l, typename map<S, T>::iterator r, const T &v);

using ll = long long;
using ull = unsigned long long;
using ld = long double;
const long long MOD = 1e9 + 7;
const long long INF = 1e18;

/**
 * Verify: http://judge.u-aizu.ac.jp/onlinejudge/review.jsp?rid=4529260
 * @tparam E
 * @tparam T
 */
template<typename E, typename T>
class LazySegmentTree {
 private:
  E _e_id;
  T _t_id;
  size_t _size;
  /** E・E */
  function<E(E, E)> _ee;
  /** E・T */
  function<E(E, T)> _et;
  /** T・T */
  function<T(T, T)> _tt;
  /** 区間加算のとき、RSQ なら掛け算、RMQ なら T をそのまま返す関数 */
  function<T(T, ll)> _t_pow;

  /**
   * k の部分木の葉に一様に value を適用する
   * @param k
   */
  void _apply_to_subtree(int k, T value) {
    _tree[k] = _et(_tree[k], _t_pow(value, _leaves_counts[k]));
    if (k < _size) {
      _lazy[k] = _tt(_lazy[k], value);
    }
  }

  /**
   * k とその親たちの遅延配列を評価する
   * @param k
   */
  void _eval_parents(int k) {
    int v = k;
    int h = 0;
    while ((v >> h) > 1) h++;
    for (; h > 0; h--) {
      k = v >> h;
      _apply_to_subtree(k << 1, _lazy[k]);
      _apply_to_subtree(k << 1 | 1, _lazy[k]);
      _lazy[k] = _t_id;
    }
  }

  /**
   * _tree[k] の親たちを最新化する
   * @param k
   */
  void _update_parents(int k) {
    k >>= 1;
    while (k > 0) {
      _tree[k] = _et(
          _ee(_tree[k << 1], _tree[k << 1 | 1]),
          _t_pow(_lazy[k], _leaves_counts[k]));
      k >>= 1;
    }
  }

 public:
  vector<E> _tree;
  vector<T> _lazy;
  vector<ll> _leaves_counts;

  LazySegmentTree(
      const vector<E> &values,
      E e_id,
      T t_id,
      function<E(E, E)> op_ee,
      function<E(E, T)> op_et,
      function<T(T, T)> op_tt,
      function<T(T, ll)> t_pow = [](T e, ll n) { return e; }
  ) : _e_id(e_id),
      _t_id(t_id),
      _ee(std::move(op_ee)),
      _et(std::move(op_et)),
      _tt(std::move(op_tt)),
      _t_pow(std::move(t_pow)) {
    _size = values.size();
    _tree.resize(_size * 2, _e_id);
    _lazy.resize(_size * 2, _t_id);
    _leaves_counts.resize(_size * 2, 1);

    for (int i = 0; i < _size; i++) {
      _tree[i + _size] = values[i];
    }
    for (int i = _size - 1; i > 0; i--) {
      _tree[i] = _ee(_tree[i << 1], _tree[i << 1 | 1]);
      _leaves_counts[i] = _leaves_counts[i << 1] + _leaves_counts[i << 1 | 1];
    }
  }

  /**
   * [l, r) の範囲に value を適用する
   * @param l
   * @param r
   * @param value
   */
  void apply(int l, int r, T value) {
    l += _size;
    r += _size;
    int l0 = l;
    int r0 = r;

    // _et が上書き系の演算のときに、あとから古い値で上書きされないように、
    // 既存の遅延配列の値を評価して _tree に移しておく
    _eval_parents(l);
    _eval_parents(r - 1);
    while (l < r) {
      if (l & 1) {
        _apply_to_subtree(l++, value);
      }
      if (r & 1) {
        _apply_to_subtree(--r, value);
      }
      l >>= 1;
      r >>= 1;
    }
    _update_parents(l0);
    _update_parents(r0 - 1);
  }

  /**
   * [l, r) に op_ee を適用した値を返す
   * @param l
   * @param r
   */
  auto query(int l, int r) -> E {
    l += _size;
    r += _size;
    _eval_parents(l);
    _eval_parents(r - 1);

    vector<E> ret, ret_r;
    while (l < r) {
      if (l & 1) {
        ret.push_back(_tree[l++]);
      }
      if (r & 1) {
        ret_r.push_back(_tree[--r]);
      }
      l >>= 1;
      r >>= 1;
    }
    reverse(ret_r.begin(), ret_r.end());
    ret.insert(ret.end(), ret_r.begin(), ret_r.end());
    return accumulate(ret.begin(), ret.end(), _e_id, _ee);
  }
};

auto main() -> int {
  cout << fixed << setprecision(10);
  cin.tie(nullptr);
  ios::sync_with_stdio(false);
  ifstream ifs;
  if (DEBUG) {
    ifs.open("src/_in.txt");
    cin.rdbuf(ifs.rdbuf());
  }

  ll N, Q;
  cin >> N >> Q;
  
  using E = ll;
  using T = ll;
  vector<E> values(N, pow(2, 31) - 1);
  E e_id = pow(2, 31) - 1;
  T t_id = INF;
  auto op_ee = [](E a, E b) { return min(a, b); };
  auto op_et = [](E a, T b) { return b == INF ? a : b; };
  auto op_tt = [](E a, T b) { return b == INF ? a : b; };
  auto st = LazySegmentTree<E, T>(values, e_id, t_id, op_ee, op_et, op_tt);

  rep (i, Q) {
    ll op;
    cin >> op;
    if (op == 0) {
      int s, t, x;
      cin >> s >> t >> x;
      st.apply(s, t + 1, x);
    } else {
      int s, t;
      cin >> s >> t;
      auto a = st.query(s, t + 1);
      cout << a << "\n";
    }
  }
}


Measured memory_bytes: 8376