Problem: Write a program which manipulates a sequence A = {a0, a1, . . . , an−1} with the following operations:

* update(s, t, x): change as, as+1, ..., at to x.
* find(s, t): report the minimum element in as, as+1, ..., at.



Note that the initial values of ai (i = 0, 1, . . . , n−1) are 231-1.

Constraints

* 1 ≤ n ≤ 100000
* 1 ≤ q ≤ 100000
* 0 ≤ s ≤ t < n
* 0 ≤ x < 231−1

Input


n q
query1
query2
:
queryq


In the first line, n (the number of elements in A) and q (the number of queries) are given. Then, ith query queryi is given in the following format:


0 s t x


or


1 s t


The first digit represents the type of the query. '0' denotes update(s, t, x) and '1' denotes find(s, t).

Output

For each find operation, print the minimum value.

Examples

Input

3 5
0 0 1 1
0 1 2 3
0 2 2 2
1 0 2
1 1 2


Output

1
2


Input

1 3
1 0 0
0 0 0 5
1 0 0


Output

2147483647
5

Solution (in CPP):

Solution:
#include "bits/stdc++.h"
using namespace std;
#define Would
#define you
const long long INF = 9999999999999999999;
const int MOD = 1e9 + 7;
const double pi = 3.141592653589793238;
const int SIZE = 1 << 17;

template<typename T>
struct lazysegtree {
	T node[2 * SIZE], lazy[2 * SIZE], mon;
	bool used[2 * SIZE];
	T(*upd_f)(T, T, int, int), (*qry_f)(T, T);
	lazysegtree(T(*op1)(T, T, int, int), T(*op2)(T, T), T X) {
		upd_f = op1;
		qry_f = op2;
		mon = X;
		fill(lazy, lazy + 2 * SIZE, mon);
		fill(node, node + 2 * SIZE, mon);
		fill(used, used + 2 * SIZE, false);
	}

	void lazy_eval(int a, int b, int c) {
		if (!used[a]) { return; }
		node[a] = upd_f(node[a], lazy[a], b, c);
		if (c - b > 1) {
			lazy[2 * a + 1] = upd_f(lazy[2 * a + 1], lazy[a], 0, 1);
			lazy[2 * a + 2] = upd_f(lazy[2 * a + 2], lazy[a], 0, 1);
			used[2 * a + 1] = used[2 * a + 2] = true;
		}
		lazy[a] = mon;
		used[a] = false;
	}

	void update(int a, int b, T val, int c = 0, int d = SIZE, int e = 0) {
		lazy_eval(e, c, d);
		if (b <= c || d <= a) { return; }
		if (a <= c && d <= b) {
			lazy[e] = upd_f(lazy[e], val, 0, 1);
			used[e] = true;
			lazy_eval(e, c, d);
		}
		else {
			int monn = (c + d) / 2;
			update(a, b, val, c, monn, 2 * e + 1);
			update(a, b, val, monn, d, 2 * e + 2);
			node[e] = qry_f(node[2 * e + 1], node[2 * e + 2]);
		}
	}

	T query(int a, int b, int c = 0, int d = SIZE, int e = 0) {
		lazy_eval(e, c, d);
		if (b <= c || d <= a) { return mon; }
		if (a <= c && d <= b) { return node[e]; }
		int monn = (c + d) / 2;
		T lmon = query(a, b, c, monn, 2 * e + 1);
		T rmon = query(a, b, monn, d, 2 * e + 2);
		return qry_f(lmon, rmon);
	}
};

int upd(int a, int b, int c, int d) { return b; }
int fin(int a, int b) { return min(a, b); }
lazysegtree<int>seg(upd, fin, INT_MAX);

//ex(DSL_2)
int main() {
	int a, b;
	cin >> a >> b;
	while (b--) {
		int n;
		cin >> n;
		if (n) {
			int c, d;
			cin >> c >> d;
			cout << seg.query(c, d + 1) << endl;
		}
		else {
			int c, d, e;
			cin >> c >> d >> e;
			seg.update(c, d + 1, e);
		}
	}
}