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;

class lazy_segtree {
    private:
        int size;
        vector<int> node,lazy;
    public:
        lazy_segtree(int n_) {
            size=1;
            while (size<n_) size*=2;
            node.resize(2*size, INT_MAX);
            lazy.resize(2*size, -1);
        }

        void setlazy(int k, int v) {
            if (2*size-1<=k) return ;
            lazy[k] = v;
            node[k] = v;
        }

        void push(int k) {
            if (lazy[k] == -1) return ;
            setlazy(k * 2 + 1, lazy[k]);
            setlazy(k * 2 + 2, lazy[k]);
            lazy[k] = -1;
        }

        void merge(int k) {
            node[k]=min(node[k*2+1],node[k*2+2]);
        }

        void range_update(int queryL,int queryR,int val,int k=0,int nodeL=0,int nodeR=-1) {
            if (nodeR==-1) nodeR=size;
            if (nodeR<=queryL || queryR<=nodeL) return ;
            if (queryL<=nodeL && nodeR<=queryR) {
                setlazy(k,val);
                return ;
            }
            else {
                push(k);
                int nodeM=(nodeL+nodeR)/2;
                range_update(queryL,queryR,val,k*2+1,nodeL,nodeM);
                range_update(queryL,queryR,val,k*2+2,nodeM,nodeR);
                merge(k);
                return ;
            }
        }

        int get_node(int queryL,int queryR,int k=0,int nodeL=0,int nodeR=-1) {
            if (nodeR==-1) nodeR=size;
            if (nodeR<=queryL || queryR<=nodeL) return INT_MAX;
            if (queryL<=nodeL && nodeR<=queryR) return node[k];
            else {
                push(k);
                int nodeM=(nodeL+nodeR)/2;
                int vl=get_node(queryL,queryR,k*2+1,nodeL,nodeM);
                int vr=get_node(queryL,queryR,k*2+2,nodeM,nodeR);
                return min(vl,vr);
            }
        }
};

int n,q;

int main(){
    cin >> n >> q;
    lazy_segtree ls(n);
    for (int i=0; i<q; i++) {
        int que,s,t,x,idx;
        cin >> que;
        if (que==0) {
            cin >> s >> t >> x;
            ls.range_update(s,t+1,x);
        }
        else {
            cin >> s >> t ;
            cout << ls.get_node(s,t+1) << endl;
        }
    }
    return 0;
}