// Slower C++ solution:
#include <iostream>

#include <algorithm>

#include <array>

#include <cstdint>

#include <functional>

#include <map>

#include <math.h>

#include <queue>

#include <set>

#include <stack>

#include <stdlib.h>

#include <string>

#include <time.h>

#include <utility>

#include <vector>



#define INF 1000000000

#define MOD 1000000007

#define rep(i,a,b) for(uint32 i = (a); i < (b); ++i)

#define bitget(a,b) (((a) >> (b)) & 1)

#define ALL(x) (x).begin(),(x).end()

#define C(x) std::cout << #x << " : " << x << std::endl

#define scanf scanf_s



using int32 = std::int_fast32_t;

using int64 = std::int_fast64_t;

using uint32 = std::uint_fast32_t;

using uint64 = std::uint_fast64_t;



#include <iostream>

#include <algorithm>

#include <array>

#include <cstdint>

#include <functional>

#include <map>

#include <math.h>

#include <queue>

#include <set>

#include <stack>

#include <stdlib.h>

#include <string>

#include <time.h>

#include <utility>

#include <vector>



#define INF 1000000000

#define MOD 1000000007

#define rep(i,a,b) for(uint32 i = (a); i < (b); ++i)

#define bitget(a,b) (((a) >> (b)) & 1)

#define ALL(x) (x).begin(),(x).end()

#define C(x) std::cout << #x << " : " << x << std::endl

#define scanf scanf_s



using int32 = std::int_fast32_t;

using int64 = std::int_fast64_t;

using uint32 = std::uint_fast32_t;

using uint64 = std::uint_fast64_t;

template<typename Monoid, typename Operand>

struct RBnode {

	RBnode *ch[2], *par;

	Monoid value, sum;

	Operand lazy;

	uint32 size, height;

	bool color, reversed;//true=black

};

template<typename Monoid, typename Operand>

class RBTrees {

	using Node = RBnode<Monoid, Operand>;

	std::vector<Node> nodes;

	uint32 itr;

	bool balanced;

	Node *backup;

public:

	RBTrees(size_t maxsize) {

		nodes.resize(maxsize + 1);

		itr = 0;

		nodes[0].ch[0] = &nodes[0];

		nodes[0].ch[1] = &nodes[0];

		nodes[0].par = nullptr;

		nodes[0].size = 0;

		nodes[0].height = 1;

		nodes[0].color = 1;

	}

	Node *nil(void) {

		return &nodes[0];

	}

	Node *recalc(Node *node) {

		node->sum = node->value;

		if (node->ch[0] != &nodes[0]) {

			node->sum = node->ch[0]->sum + node->sum;

		}

		if (node->ch[1] != &nodes[0]) {

			node->sum = node->sum + node->ch[1]->sum;

		}

		node->size = node->ch[0]->size + 1 + node->ch[1]->size;

		return node;

	}

	void push(Node *node) {

		node->ch[0]->lazy = node->ch[0]->lazy * node->lazy;

		node->ch[1]->lazy = node->ch[1]->lazy * node->lazy;

		node->value = node->value * node->lazy;

		node->sum = node->sum * node->lazy;

		node->lazy.inactive();

		if (node->reversed) {

			node->ch[0]->reversed ^= 1;

			node->ch[1]->reversed ^= 1;

			std::swap(node->ch[0], node->ch[1]);

			node->sum.reverse();

			node->value.reverse();

			node->reversed = 0;

		}

		return;

	}

	Node *rotate(Node *node, uint32 dir) {

		Node *t = node->ch[dir ^ 1];

		node->ch[dir ^ 1] = t->ch[dir];

		t->ch[dir]->par = node;

		node->height = t->ch[dir]->height;

		t->height = node->height + node->color;

		t->color = node->color;

		node->color = 0;

		t->par = node->par;

		node->par = t;

		t->ch[dir] = recalc(node);

		return recalc(t);

	}

	Node *insert(Node *root, const Monoid &value, uint32 position) {

		nodes[++itr].ch[0] = &nodes[0];

		nodes[itr].ch[1] = &nodes[0];

		nodes[itr].value = value;

		nodes[itr].sum = value;

		nodes[itr].lazy.inactive();

		nodes[itr].size = 1;

		nodes[itr].height = 1;

		nodes[itr].color = 0;

		nodes[itr].reversed = 0;

		backup = nullptr;

		push(root);

		root = _subinsert(root, position);

		if (!root->color) {

			root->height += 1;

			root->color = 1;

		}

		return root;

	}

	Node *_subinsert(Node *node, uint32 pos) {

		if (node == &nodes[0]) {

			balanced = 1;

			nodes[itr].par = backup;

			return &nodes[itr];

		}

		backup = node;

		push(node->ch[0]);

		push(node->ch[1]);

		if (node->ch[0]->size < pos) {

			node->ch[1] = _subinsert(node->ch[1], pos - node->ch[0]->size - 1);

			if (balanced) {

				return _insertadjust(node, 1);

			}

		}

		else {

			node->ch[0] = _subinsert(node->ch[0], pos);

			if (balanced) {

				return _insertadjust(node, 0);

			}

		}

		return recalc(node);

	}

	Node *_insertadjust(Node *node, uint32 dir) {

		if (!node->color) {

			return recalc(node);

		}

		if (!node->ch[dir ^ 1]->color) {

			if (node->ch[dir]->ch[dir]->color&&node->ch[dir]->ch[dir ^ 1]->color) {

				balanced = 0;

				return recalc(node);

			}

			return flip(recalc(node));

		}

		balanced = 0;

		if (node->ch[dir]->ch[dir]->color) {

			if (node->ch[dir]->ch[dir ^ 1]->color) {

				return recalc(node);

			}

			else {

				node->ch[dir] = rotate(node->ch[dir], dir);

				return rotate(node, dir ^ 1);

			}

		}

		else {

			if (node->ch[dir]->ch[dir ^ 1]->color) {

				return rotate(node, dir ^ 1);

			}

			else {

				node->ch[dir] = rotate(node->ch[dir], dir);

				balanced = 1;

				node = rotate(node, dir ^ 1);

				return flip(node);

			}

		}

	}

	Node *flip(Node *node) {

		node->ch[0]->color = 1;

		node->ch[0]->height += 1;

		node->ch[1]->color = 1;

		node->ch[1]->height += 1;

		node->color = 0;

		return node;

	}

	Node *access(Node *root, uint32 position) {

		while (root->ch[0]->size != position) {

			if (position > root->ch[0]->size) {

				position -= root->ch[0]->size + 1;

				root = root->ch[1];

			}

			else {

				root = root->ch[0];

			}

		}

		return root;

	}

	Node *erase(Node *root, uint32 position) {

		push(root);

		return _suberase(root, position);

	}

	Node *_suberase(Node *node, uint32 position) {

		push(node->ch[0]);

		push(node->ch[1]);

		if (node->ch[0]->size > position) {

			node->ch[0] = _suberase(node->ch[0], position);

			if (balanced) {

				return _eraseadjust(node, 0);

			}

			return recalc(node);

		}

		if (node->ch[0]->size < position) {

			node->ch[1] = _suberase(node->ch[1], position - node->ch[0]->size - 1);

			if (balanced) {

				return _eraseadjust(node, 1);

			}

			return recalc(node);

		}

		if (node->ch[0] != &nodes[0]) {

			if (node->ch[1] != &nodes[0]) {

				node->ch[1] = _suberase(node->ch[1], 0);

				node->value = backup->value;

				if (balanced) {

					return _eraseadjust(node, 1);

				}

				return recalc(node);

			}

			node->ch[0]->par = node->par;

			node->ch[0]->color = 1;

			++node->ch[0]->height;

			balanced = 0;

			return node->ch[0];

		}

		backup = node;

		if (node->ch[1] != &nodes[0]) {

			node->ch[1]->par = node->par;

			node->ch[1]->color = 1;

			++node->ch[1]->height;

			balanced = 0;

			return node->ch[1];

		}

		balanced = node->color;

		return &nodes[0];

	}

	Node *_eraseadjust(Node *node, uint32 dir) {

		if (node->ch[dir ^ 1]->ch[0]->color&&node->ch[dir ^ 1]->ch[1]->color) {

			if (node->ch[dir ^ 1]->color) {

				node->ch[dir ^ 1]->color = 0;

				--node->ch[dir ^ 1]->height;

				balanced = node->color;

				node->height -= node->color;

				node->color = 1;

				return recalc(node);

			}

			push(node->ch[dir ^ 1]->ch[0]);

			push(node->ch[dir ^ 1]->ch[1]);

			node = rotate(node, dir);

			node->ch[dir] = _eraseadjust(node->ch[dir], dir);

			return node;

		}

		balanced = 0;

		push(node->ch[dir ^ 1]->ch[0]);

		push(node->ch[dir ^ 1]->ch[1]);

		if (node->ch[dir ^ 1]->ch[dir ^ 1]->color) {

			push(node->ch[dir ^ 1]->ch[dir]->ch[0]);

			push(node->ch[dir ^ 1]->ch[dir]->ch[1]);

			node->ch[dir ^ 1] = rotate(node->ch[dir ^ 1], dir ^ 1);

		}

		node = rotate(node, dir);

		++node->height;

		++node->ch[0]->height;

		node->ch[0]->color = 1;

		++node->ch[1]->height;

		node->ch[1]->color = 1;

		return node;

	}

	Monoid range(Node *root, uint32 begin, uint32 end) {

		Node *t = root;

		Monoid ret;

		while (1) {

			push(t);

			if (t->ch[0]->size < begin) {

				begin -= t->ch[0]->size + 1;

				end -= t->ch[0]->size + 1;

				t = t->ch[1];

				continue;

			}

			if (t->ch[0]->size < end) {

				end -= t->ch[0]->size + 1;

				ret = t->value;

				root = t->ch[0];

				t = t->ch[1];

				break;

			}

			t = t->ch[0];

		}

		while (root != &nodes[0]) {

			push(root);

			if (root->ch[0]->size < begin) {

				begin -= root->ch[0]->size + 1;

				root = root->ch[1];

				continue;

			}

			if (root->ch[1] != &nodes[0]) {

				push(root->ch[1]);

				ret = (root->value + root->ch[1]->sum) + ret;

			}

			else ret = root->value + ret;

			root = root->ch[0];

		}

		while (t != &nodes[0]) {

			push(t);

			if (t->ch[0]->size < end) {

				end -= t->ch[0]->size + 1;

				if (t->ch[0] != &nodes[0]) {

					push(t->ch[0]);

					ret = ret + (t->ch[0]->sum + t->value);

				}

				else ret = ret + t->value;

				t = t->ch[1];

				continue;

			}

			t = t->ch[0];

		}

		return ret;

	}

	void update(Node *root, uint32 begin, uint32 end, const Operand &data) {

		Node *t = root;

		push(t);

		while (1) {

			push(t->ch[0]);

			push(t->ch[1]);

			if (t->ch[0]->size < begin) {

				begin -= t->ch[0]->size + 1;

				end -= t->ch[0]->size + 1;

				t = t->ch[1];

				continue;

			}

			if (t->ch[0]->size < end) {

				end -= t->ch[0]->size + 1;

				t->value = t->value*data;

				backup = t;

				break;

			}

			t = t->ch[0];

		}

		root = t->ch[0];

		while (root != &nodes[0]) {

			backup = root;

			if (root->ch[0]->size < begin) {

				begin -= root->ch[0]->size + 1;

				push(root->ch[0]);

				push(root->ch[1]);

				root = root->ch[1];

				continue;

			}

			root->value = root->value*data;

			root->ch[1]->lazy = root->ch[1]->lazy*data;

			push(root->ch[0]);

			push(root->ch[1]);

			root = root->ch[0];

		}

		while (backup != t) {

			backup = recalc(backup)->par;

		}

		root = t->ch[1];

		while (root != &nodes[0]) {

			t = root;

			if (root->ch[0]->size < end) {

				end -= root->ch[0]->size + 1;

				root->value = root->value*data;

				root->ch[0]->lazy = root->ch[0]->lazy*data;

				push(root->ch[0]);

				push(root->ch[1]);

				root = root->ch[1];

				continue;

			}

			push(root->ch[0]);

			push(root->ch[1]);

			root = root->ch[0];

		}

		while (t != nullptr) {

			t = recalc(t)->par;

		}

		return;

	}

	Node *_submerge(Node *left, Node *right, Node *mid) {

		uint32 dir = 1;

		if (left->height < right->height) {

			dir = 0;

			std::swap(left, right);

		}

		if (right == &nodes[0]) {

			uint32 t = itr;

			itr = (mid - &nodes[0]) - 1;

			if (dir) {

				left = insert(left, mid->value, left->size);

			}

			else {

				left = insert(left, mid->value, 0);

			}

			itr = t;

			return left;

		}

		push(left);

		push(right);

		while (left->height != right->height) {

			push(left->ch[0]);

			push(left->ch[1]);

			left = left->ch[dir];

		}

		mid->ch[dir ^ 1] = left;

		mid->ch[dir] = right;

		recalc(mid)->par = left->par;

		mid->height = left->height;

		mid->color = 0;

		left->par = mid;

		right->par = mid;

		push(left->ch[0]);

		push(left->ch[1]);

		balanced = 1;

		while (mid->par != nullptr) {

			mid->par->ch[dir] = mid;

			mid = mid->par;

			if (balanced) {

				mid = _insertadjust(mid, dir);

			}

			else {

				recalc(mid);

			}

		}

		if (!mid->color) {

			++mid->height;

			mid->color = 1;

		}

		return mid;

	}

	Node *merge(Node *left, Node *right) {

		if (right == &nodes[0]) {

			return left;

		}

		right = erase(right, 0);

		return _submerge(left, right, backup);

	}

	void show(Node *node) {

		std::cout << "(";

		if (node->ch[0] != &nodes[0]) {

			show(node->ch[0]);

			std::cout << "←";

		}

		std::cout << node->size << " " << (node->color?"黒":"赤") << " " << node->height;

		if (node->ch[1] != &nodes[0]) {

			std::cout << "→";

			show(node->ch[1]);

		}

		std::cout << ")";

		return;

	}

	void check(Node *node) {

		if (node->ch[0] != &nodes[0]) {

			if (node->ch[0]->par != node)

				std::cerr << "#\n";

			check(node->ch[0]);

		}

		if (node->ch[1] != &nodes[0]) {

			if (node->ch[1]->par != node)

				std::cerr << "#\n";

			check(node->ch[1]);

		}

	}

};

struct SUB {

	int32 e;

	bool a;

	SUB() { inactive(); }

	SUB(int32 x, bool y) { e = x; a = y; }

	void inactive(void) {

		a = false;

	}

	SUB operator*(const SUB &other) {

		if (other.a) return other;

		return *this;

	}

};

struct MIN {

	int32 e;

	MIN() { set(); }

	MIN(int32 x) { e = x; }

	void set() { e = 2147483647; }

	void reverse(void) {}

	MIN operator+(const MIN &other) {

		if (e < other.e) return *this;

		return other;

	};

	MIN operator*(const SUB &other) {

		if (other.a) return MIN(other.e);

		return *this;

	}

};

int main(void) {

	std::ios::sync_with_stdio(false);

	std::cin.tie(0);

	uint32 n, q;

	std::cin >> n >> q;

	RBTrees<MIN, SUB> T(n);

	RBnode<MIN, SUB> *r = T.nil();

	uint32 c;

	uint32 s, t;

	SUB x;

	x.a = 1;

	//*

	rep(i, 0, n) {

		RBnode<MIN, SUB> *A;

		A = T.insert(T.nil(), MIN(2147483647), 0);

		r = T.merge(A, r);

		//T.show(r);std::cout << "\n";T.check(r);

	}

	/*/

	std::queue<RBnode<MIN, SUB> *> Q;

	rep(i, 0, n) {

		Q.push(T.insert(r, MIN(2147483647), 0));

	}

	while (Q.size() != 1) {

		RBnode<MIN, SUB> *A, *B;

		A = Q.front();Q.pop();

		B = Q.front();Q.pop();

		Q.push(T.merge(A, B));

	}

	r = Q.front();Q.pop();

	//*/

	//T.show(r);std::cout << "\n";T.check(r);

	rep(i, 0, q) {

		std::cin >> c >> s >> t;

		if (c == 0) {

			std::cin >> x.e;

			T.update(r, s, t + 1, x);

			//T.show(r);std::cout << "\n";T.check(r);

		}

		else {

			std::cout << T.range(r, s, t + 1).e << "\n";

		}

	}

	return 0;

}


// Faster C++ solution for the same problem (measured speedup: 1.1101045059309165x):
//#define NDEBUG

#define _CRT_SECURE_NO_WARNINGS

#include <cassert>

#include <functional>

#include <utility>

#include <vector>



template <typename ValueMonoid, typename OperatorMonoid> class LazySegmentTree {

public:

	using value_type = ValueMonoid;

	using reference = value_type &;

	using const_reference = const value_type &;

	using operator_type = OperatorMonoid;



private:

	using operator_constref = const operator_type &;

	using container_type = std::vector<std::pair<value_type, operator_type>>;



public:

	using size_type = typename container_type::size_type;



private:

	using F = std::function<value_type(const_reference, const_reference)>;

	using G = std::function<operator_type(operator_constref, operator_constref)>;

	using H = std::function<value_type(const_reference, operator_constref)>;

	const F f;

	const G g;

	const H h;

	const value_type v_neutral;

	const operator_type o_neutral;

	size_type height, size_;

	container_type tree;

	static size_type getheight(const size_type size) {

		size_type ret = 0;

		while ((size_type)1 << ret < size)

			++ret;

		return ret;

	}

	value_type reflect(const size_type index) {

		return h(tree[index].first, tree[index].second);

	}

	void recalc(const size_type index) {

		tree[index].first = f(reflect(index << 1), reflect(index << 1 | 1));

	}

	void assign(const size_type index, operator_constref data) {

		tree[index].second = g(tree[index].second, data);

	}

	void push(const size_type index) {

		assign(index << 1, tree[index].second);

		assign(index << 1 | 1, tree[index].second);

		tree[index].second = o_neutral;

	}

	void propagate(const size_type index) {

		for (size_type i = height; i; --i)

			push(index >> i);

	}

	void thrust(const size_type index) {

		tree[index].first = reflect(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);

	}



public:

	LazySegmentTree(

		const size_type size, const F &value_addition = std::plus<value_type>(),

		const_reference value_neutral = value_type(),

		const G &operator_multiplication = std::multiplies<operator_type>(),

		operator_constref operator_neutral = operator_type(),

		const H &mutual_multiplication =

		[](const_reference l, operator_constref r) { return l * r; })

		: f(value_addition), v_neutral(value_neutral), g(operator_multiplication),

		o_neutral(operator_neutral), h(mutual_multiplication),

		height(getheight(size)), size_((size_type)1 << height),

		tree(size_ << 1, std::make_pair(v_neutral, o_neutral)) {}

	void update(size_type begin, size_type end, operator_constref data) {

		assert(begin <= end);

		assert(begin <= size_);

		assert(end <= size_);

		begin += size_;

		end += size_;

		propagate(begin);

		propagate(end - 1);

		for (size_type left = begin, right = end; left < right;

			left >>= 1, right >>= 1) {

			if (left & 1)

				assign(left++, data);

			if (right & 1)

				assign(right - 1, data);

		}

		build(begin);

		build(end - 1);

	}

	void update(size_type index,

		const std::function<value_type(const_reference)> &e) {

		assert(index < size_);

		index += size_;

		propagate(index);

		tree[index].first = e(reflect(index));

		tree[index].second = o_neutral;

		build(index);

	}

	void update(const size_type index, const_reference data) {

		assert(index < size_);

		update(index, [&data](const_reference d) { return data; });

	}

	value_type range(size_type begin, size_type end) {

		assert(begin <= end);

		assert(begin <= size_);

		assert(end <= size_);

		begin += size_;

		end += size_;

		evaluate(begin);

		evaluate(end - 1);

		value_type retL = v_neutral, retR = v_neutral;

		for (; begin < end; begin >>= 1, end >>= 1) {

			if (begin & 1)

				retL = f(retL, reflect(begin++));

			if (end & 1)

				retR = f(reflect(end - 1), retR);

		}

		return f(retL, retR);

	}

	size_type search(const std::function<bool(const_reference)> &b) {

		if (!b(reflect(1)))

			return size_;

		value_type acc = v_neutral;

		size_type i = 1;

		while (i < size) {

			thrust(i);

			if (!b(f(acc, reflect(i <<= 1))))

				acc = f(acc, reflect(i++));

		}

		return i - size_;

	}

	size_type size() const { return size_; }

};



#include <algorithm>

#include <limits>

template<typename T>

struct Assign {

	T a;

	bool f;

	Assign():f(1){}

	Assign(const T &x):a(x),f(0){}

	Assign operator*(const Assign &o)const {

		return o.f ? *this : o;

	}

};

template<typename T>

struct Mini {

	T a;

	Mini(const T &x=std::numeric_limits<T>::max()):a(x){}

	Mini operator+(const Mini &o)const {

		return Mini(std::min(a, o.a));

	}

	Mini operator*(const Assign<T> &o)const {

		return o.f ? *this : Mini(o.a);

	}

};





#include <cstdio>

#include <algorithm>



int main(void) {

	using M = Mini<int>;

	using A = Assign<int>;

	int n, q;

	scanf("%d %d", &n, &q);

	LazySegmentTree<M, A> T(n, std::plus<M>(), M(2147483647));

	while (q--) {

		int c, s, t, x;

		scanf("%d %d %d", &c, &s, &t);

		if (c) {

			printf("%d\n", T.range(s, t + 1).a);

		}

		else {

			scanf("%d", &x);

			T.update(s, t + 1, A(x));

		}

	}

	return 0;

}