#include <cassert>
#include <functional>
#include <stdexcept>
#include <utility>
#include <vector>

template <class ValueMonoid, class OperatorMonoid, class Modifier,
	template <class> class Container>
class lazy_segment_tree {
public:
	using value_structure = ValueMonoid;
	using value_type = typename value_structure::value_type;
	using operator_structure = OperatorMonoid;
	using operator_type = typename operator_structure::value_type;
	using modifier_type = Modifier;
	using container_type = Container<::std::pair<value_type, operator_type>>;
	using size_type = typename container_type::size_type;

private:
	using e_cref = typename container_type::const_reference;
	using e_ref = typename container_type::reference;
	size_type size_, height;
	container_type c;
	static size_type getheight(const size_type size) noexcept {
		size_type ret = 0;
		while (static_cast<size_type>(1) << ret < size)
			++ret;
		return ret;
	}
	static value_type reflect(e_cref element) {
		return modifier_type::operation(element.first, element.second);
	}
	void recalc(const size_type index) {
		c[index].first = value_structure::operation(reflect(c[index << 1]) ,
			reflect(c[index << 1 | 1]));
	}
	static void assign(operator_type &element, const operator_type &data) {
		element = operator_structure::operation(element, data);
	}
	void push(const size_type index) {
		assign(c[index << 1].second, c[index].second);
		assign(c[index << 1 | 1].second, c[index].second);
		c[index].second = operator_structure::identity();
	}
	void propagate(const size_type index) {
		for (size_type i = height; i; --i)
			push(index >> i);
	}
	void thrust(const size_type index) {
		c[index].first = reflect(c[index]);
		push(index);
	}
	void evaluate(const size_type index) {
		for (size_type i = height; i; --i)
			thrust(index >> i);
	}
	void build(size_type index) {
		while (index >>= 1)
			recalc(index);
	}
	size_type base_size() const { return static_cast<size_type>(1) << height; }

public:
	lazy_segment_tree() : size_(0), height(0), c() {}
	explicit lazy_segment_tree(const size_type size)
		: size_(size), height(getheight(size_)),
		c(static_cast<size_type>(1) << (height + 1),
		{ value_structure::identity(), operator_structure::identity() }) {}

	bool empty() const { return !size_; }
	size_type size() const { return size_; }

	const value_type &operator[](size_type index) {
		assert(index < size());
		index += base_size();
		evaluate(index);
		c[index].first = reflect(c[index]);
		c[index].second = operator_structure::identity();
		return c[index].first;
	}
	const value_type &at(size_type index) {
		if (index < size()) {
			throw ::std::out_of_range("index out of range");
		}
		else {
			index += base_size();
			evaluate(index);
			c[index].first = reflect(c[index]);
			c[index].second = operator_structure::identity();
			return c[index].first;
		}
	}
	value_type fold(size_type first, size_type last) {
		assert(first <= last);
		assert(first <= size());
		assert(last <= size());
		first += base_size();
		last += base_size();
		evaluate(first);
		evaluate(last - 1);
		value_type retL = value_structure::identity(),
			retR = value_structure::identity();
		for (; first < last; first >>= 1, last >>= 1) {
			if (first & 1)
				retL = value_structure::operation(retL, reflect(c[first++]));
			if (last & 1)
				retR = value_structure::operation(reflect(c[last - 1]), retR);
		}
		return value_structure::operation(retL, retR);
	}
	template <class F> size_type search(const F &f) {
		if (f(value_structure::identity()))
			return static_cast<size_type>(0);
		if (!f(reflect(c[1])))
			return size() + 1;
		value_type acc = value_structure::identity();
		size_type i = 1;
		while (i < base_size()) {
			thrust(i);
			if (!f(value_structure::operation(acc, reflect(c[i <<= 1]))))
				acc = value_structure::operation(acc, reflect(c[i++]));
		}
		return i - base_size() + 1;
	}

	void update(const size_type index, const value_type &data) {
		assert(index < size());
		index += base_size();
		propagate(index);
		c[index].first = data;
		c[index].second = operator_structure::identity();
		build(index);
	}
	template <class F> void update(size_type index, const F &f) {
		assert(index < size());
		index += base_size();
		propagate(index);
		c[index].first = f(reflect(index));
		c[index].second = operator_structure::identity();
		build(index);
	}
	void update(size_type first, size_type last, const operator_type data) {
		assert(first <= last);
		assert(first <= size());
		assert(last <= size());
		first += base_size();
		last += base_size();
		propagate(first);
		propagate(last - 1);
		for (size_type left = first, right = last; left < right;
			left >>= 1, right >>= 1) {
			if (left & 1)
				assign(c[left++].second, data);
			if (right & 1)
				assign(c[right - 1].second, data);
		}
		build(first);
		build(last - 1);
	}
};

#include <algorithm>
#include <limits>
template <class T> class min_monoid {
public:
	using value_type = T;
	static value_type operation(const value_type &x, const value_type &y) {
		return ::std::min(x, y);
	}
	static value_type identity() {
		return ::std::numeric_limits<value_type>::max();
	}
	static value_type reverse(const value_type &x) { return x; }
};

#include <utility>
template <class T> class assign_monoid {
public:
	using value_type = ::std::pair<T, bool>;
	static value_type operation(const value_type &x, const value_type &y) {
		return y.second ? y : x;
	}
	static value_type identity() { return value_type(T(), 0); }
	static value_type reverse(const value_type &x) { return x; }
};

template <class T> class minmax_assign {
public:
	static T operation(const T &x, const ::std::pair<T, bool> &y) {
		return y.second ? y.first : x;
	}
};

#include <iostream>
#include <vector>

template<class T>
using vec = ::std::vector<T>;

int main() {
	int n, q;
	::std::cin >> n >> q;

	lazy_segment_tree<min_monoid<int>,
					  assign_monoid<int>,
					  minmax_assign<int>,
					  vec> T(n);

	T.update(0, T.size(), { 2147483647 ,1 });

	while (q--) {
		int c, s, t, x;
		::std::cin >> c >> s >> t;

		if (c) {
			::std::cout << T.fold(s, t + 1) << ::std::endl;
		}
		else {
			::std::cin >> x;
			T.update(s, t + 1, { x,1 });
		}
	}

	return 0;
}


Measured memory_bytes: 6008