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 <iostream>
#include <queue>
#include <vector>
#include <algorithm>
#include <set>
#include <cmath>
#include <tuple>
#include <cstring>
#include <map>
#include <iomanip>
#include <ctime>
#include <complex>
#include <cassert>
#include <climits>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define _ << " " <<
#define all(X) (X).begin(), (X).end()
#define len(X) (X).size()
#define Pii pair<int, int>
#define Pll pair<ll, ll>
#define Tiii tuple<int, int, int>
#define Tlll tuple<ll, ll, ll>

class SegTree_Delay {
public:
    int f;
    int INIT = INT_MAX;
    vector<int> dat, lazy;

    SegTree_Delay(int n) {
        f = 1;
        while (f < n) f *= 2;
        dat.assign(2 * f, INIT);
        lazy.assign(2 * f, INIT);
    }

    void eval(int k) {
        if (lazy[k] == INIT) return;
        if (k < f - 1) {
            lazy[2 * k + 1] = lazy[k];
            lazy[2 * k + 2] = lazy[k];
        }
        dat[k] = lazy[k];
        lazy[k] = INIT;
    }

    void update(int a, int b, int x, int k, int l, int r) {
        eval(k);
        if (a <= l && r <= b) {
            lazy[k] = x;
            eval(k);
        }
        else if (a < r && l < b) {
            update(a, b, x, k * 2 + 1, l, (l + r) / 2);
            update(a, b, x, k * 2 + 2, (l + r) / 2, r);
            dat[k] = min(dat[k * 2 + 1], dat[k * 2 + 2]);
        }
    }

    void update(int a, int b, int x) {
        update(a, b, x, 0, 0, f);
    }

    int query(int a, int b) {
        return query(a, b, 0, 0, f);
    }

    int query(int a, int b, int k, int l, int r) {
        eval(k);
        if (r <= a || b <= l) return INIT;
        if (a <= l && r <= b) return dat[k];
        else {
            int vl = query(a, b, k * 2 + 1, l, (l + r) / 2);
            int vr = query(a, b, k * 2 + 2, (l + r) / 2, r);
            return min(vl, vr);
        }
    }
};


int main() {
    int n, q;
    cin >> n >> q;
    SegTree_Delay st = SegTree_Delay(n);
    while (q--) {
        int m;
        cin >> m;
        if (m) {
            int s, t;  cin >> s >> t;
            cout << st.query(s, t + 1) << endl;
        }
        else {
            int s, t, x;
            cin >> s >> t >> x;
            st.update(s, t + 1, x);
        }
    }
}