#include <iostream>
#include <vector>
#include <limits>
#include <cmath>

using namespace std;

const int INF = numeric_limits<int>::max();

// [begin, end) of an array
// [left, right): range of the query
// current_idx: index of the node in segment_tree corresponding to a range in the original array
void updateQuery(int segment_tree[], int lazy[], int left, int right, int begin, int end, int current_idx, int value){
	if(lazy[current_idx] != -1){
		segment_tree[current_idx] = lazy[current_idx];
		if(begin != end - 1){
			lazy[2 * current_idx + 1] = lazy[current_idx];
			lazy[2 * current_idx + 2] = lazy[current_idx];

		}
		lazy[current_idx] = -1;
	}
	if(end <= left || begin >= right){
		return;
	}
	if(left <= begin && right >= end){
		segment_tree[current_idx] = value;
		if(begin != end - 1){
			lazy[2 * current_idx + 1] = value;
			lazy[2 * current_idx + 2] = value;

		}
		return;
	}

	updateQuery(segment_tree, lazy, left, right, begin, (begin + end) / 2, 2 * current_idx + 1, value); // value of the left child (left half range)
	updateQuery(segment_tree, lazy, left, right, (begin + end) / 2, end, 2 * current_idx + 2, value); // value of the right child (right half range)
	segment_tree[current_idx] = min(segment_tree[2 * current_idx + 1], segment_tree[2 * current_idx + 2]);
}

// [left, right]
void update(int segment_tree[], int lazy[], int n, int left, int right, int value){
	updateQuery(segment_tree, lazy, left, right + 1, 0, n, 0, value);
}

// [begin, end) of an array
// [left, right): range of the query
// current_idx: index of the node in segment_tree corresponding to a range in the original array
int query(int segment_tree[], int lazy[], int left, int right, int begin, int end, int current_idx){
	if(lazy[current_idx] != -1){
		segment_tree[current_idx] = lazy[current_idx];
		if(begin != end - 1){
			lazy[2 * current_idx + 1] = lazy[current_idx];
			lazy[2 * current_idx + 2] = lazy[current_idx];

		}
		lazy[current_idx] = -1;
	}

	if(end <= left || begin >= right){
		return INF;
	}
	if(left <= begin && right >= end){
		return segment_tree[current_idx];
	}

	int left_val = query(segment_tree, lazy, left, right, begin, (begin + end) / 2, 2 * current_idx + 1); // value of the left child (left half range)
	int right_val = query(segment_tree, lazy, left, right, (begin + end) / 2, end, 2 * current_idx + 2); // value of the right child (right half range)
	return min(left_val, right_val);
}

// [left, right]
int find(int segment_tree[], int lazy[], int n, int left, int right){
	return query(segment_tree, lazy, left, right + 1, 0, n, 0);
}

int initRMQ(int original_size){
	int n = 1;
	// make the size of the array to be power of n
	while(n < original_size){
		n *= 2;
	}
	return n;
}

int main(){
	int original_size, q;
	cin >> original_size >> q;
	int n = initRMQ(original_size);
	int segment_tree[2 * n - 1];
	int lazy[2 * n - 1];
	for(auto i = 0; i < 2 * n - 1; ++i){
		segment_tree[i] = INF;
		lazy[i] = -1;
	}

	for(auto i = 0; i < q; ++i){
		int cmd;
	    cin >> cmd;
		if(cmd == 0){
			int left, right, val;
			cin >> left >> right >> val;
			update(segment_tree, lazy, n, left, right, val);
		}else if(cmd == 1){
			int left, right;
			cin >> left >> right;
			cout << find(segment_tree, lazy, n, left, right) << endl;
		}
	}
}


Measured memory_bytes: 5136