#include <iostream>
#include <iostream>
#include <vector>
#include <climits>
#include <functional>

template<typename T>
struct segment_tree {
	long long N;					// the size of V
	long long M;					// the number of leaves
	std::vector<T> V;				// Segment Tree, 1-indexed
	std::vector<T> W;				// vector for laze evaluation, 1-indexed
	std::vector<bool> flag;			// true : unevaluated elements exists under W[i]
	std::function<T(T, T)> OP1;		// binary operation for V
	std::function<T(T, T, T)> OP2;	// operation for lazy evaluation (W -> V)
	std::function<T(T, T)> OP3;		// binary operation for W
	T ID1;							// identity element of OP1
	T ID2;							// identity element of OP2 and OP3

	segment_tree(
		std::vector<T>& a,
		std::function<T(T, T)> f,
		std::function<T(T, T, T)> g,
		std::function<T(T, T)> h,
		T t1, T t2
	) : OP1(f), OP2(g), OP3(h), ID1(t1), ID2(t2) {
		M = 1;
		while (M < a.size()) M *= 2;
		N = 2 * M;
		V.resize(N, ID1); W.resize(N, ID2); flag.resize(N, false);
		for (long long i = 0; i < a.size(); i++) V[M + i] = a[i];
		for (long long i = M - 1; i > 0; i--) {
			V[i] = OP1(V[2 * i], V[2 * i + 1]);
		}
	}
	segment_tree() {}

	void init(
		std::vector<T>& a,
		std::function<T(T, T)> f,
		std::function<T(T, T, T)> g,
		std::function<T(T, T)> h,
		T t1, T t2
	) {
		OP1 = f; OP2 = g; OP3 = h; ID1 = t1; ID2 = t2;
		M = 1;
		while (M < a.size()) M *= 2;
		N = 2 * M;
		V.resize(N, ID1); W.resize(N, ID2); flag.resize(N, false);
		for (long long i = 0; i < a.size(); i++) V[M + i] = a[i];
		for (long long i = M - 1; i > 0; i--) {
			V[i] = OP1(V[2 * i], V[2 * i + 1]);
		}
	}

	void laze_eval(long long cur_node, long long width) {
		if (W[cur_node] != ID2) {
			V[cur_node] = OP2(V[cur_node], W[cur_node], width);
			if (width > 1) {
				W[cur_node * 2] = OP3(W[cur_node * 2], W[cur_node]);
				W[cur_node * 2 + 1] = OP3(W[cur_node * 2 + 1], W[cur_node]);
			}
			W[cur_node] = ID2;
		}
	}

	void range_update(
		long long l, long long r, T x,
		long long cur_node = 1,
		long long cur_left = 0, long long cur_right = -1
	) {
		if (cur_right == -1) cur_right = M;
		long long width = cur_right - cur_left;
		if (cur_right <= l || r <= cur_left) return;
		if (l <= cur_left && cur_right <= r) {
			W[cur_node] = OP3(W[cur_node], x);
		}
		else {
			laze_eval(cur_node, width);
			flag[cur_node] = true;
			long long mid = (cur_left + cur_right) / 2;
			range_update(l, r, x, cur_node * 2, cur_left, mid);
			range_update(l, r, x, cur_node * 2 + 1, mid, cur_right);
			V[cur_node] = OP1(V[cur_node * 2], V[cur_node * 2 + 1]);
		}
	}

	T range_fold(
		long long l, long long r,
		long long cur_node = 1,
		long long cur_left = 0, long long cur_right = -1
	) {
		if (cur_right == -1) cur_right = M;
		long long width = cur_right - cur_left;
		if (cur_right <= l || r <= cur_left) return ID1;
		laze_eval(cur_node, width);
		if (width == 1) {
			flag[cur_node] = false;
			return V[cur_node];
		}
		long long mid = (cur_left + cur_right) / 2;
		if (l <= cur_left && cur_right <= r && !flag[cur_node]) {
			return V[cur_node];
		}
		else if (l <= cur_left && cur_right <= r) {
			flag[cur_node] = false;
			range_fold(cur_left, mid);
			range_fold(mid, cur_right);
			return V[cur_node] = OP1(V[cur_node * 2], V[cur_node * 2 + 1]);
		}
		return OP1(
			range_fold(l, r, cur_node * 2, cur_left, mid),
			range_fold(l, r, cur_node * 2 + 1, mid, cur_right)
		);
	}
};

int main() {
	long long n, q;
	std::cin >> n >> q;
	std::vector<long long> a(n, (1ll << 31) - 1);
	auto f = [] (long long x, long long y) {return std::min(x, y);};
	auto g = [] (long long x, long long y, long long z) {return y;};
	auto h = [] (long long x, long long y) {return y;};
	segment_tree<long long> sg(a, f, g, h, (1ll << 31) - 1, (1ll << 31) - 1);
	while (q--) {
		long long z, s, t;
		std::cin >> z >> s >> t;
		if (z == 0) {
			long long x;
			std::cin >> x;
			sg.range_update(s, t + 1, x);
		} else {
			std::cout << sg.range_fold(s, t + 1) << '\n';
		}
	}
}


Measured memory_bytes: 7856