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<vector>

using namespace std;
#define int long long

const int INF=(1LL<<31)-1;
struct SegmentTree{

   static const int N=1<<17;
   vector<int> seg, lazy;
   SegmentTree(){
      seg.resize(2*N-1, INF);
      lazy.resize(2*N-1, -1);// -1:????????£???????????¨???????????¨
   }

   void setLazy(int i, int x){
      lazy[i]=x;
      seg[i]=x;
   }

   void refresh(int i, int l, int r){
      if(lazy[i]!=-1){
         /*
         seg[i]=lazy[i];
         if(r-l>1){
            lazy[2*i+1]=lazy[i];
            lazy[2*i+2]=lazy[i];
         }
         */
         setLazy(2*i+1, lazy[i]);
         setLazy(2*i+2, lazy[i]);
         lazy[i]=-1;
      }
   }

   void update(int a, int b, int x, int i=0, int l=0, int r=N){
      //refresh(i, l, r);
      if(b<=l or r<=a){
         return;
      }else if(a<=l and r<=b){
         setLazy(i, x);
         return;
      }else{
         refresh(i, l, r);
         int m=(r+l)/2;
         update(a, b, x, 2*i+1, l, m);
         update(a, b, x, 2*i+2, m, r);
         seg[i]=min(seg[2*i+1], seg[2*i+2]);
      }
   }

   int getmin(int a, int b, int i=0, int l=0, int r=N){
      //refresh(i, l, r);
      if(b<=l or r<=a){
         return INF;
      }else if(a<=l and r<=b){
         return seg[i];
      }else{
         refresh(i, l, r);
         int m=(r+l)/2;
         int vl=getmin(a, b, 2*i+1, l, m);
         int vr=getmin(a, b, 2*i+2, m, r);
         return min(vl, vr);
      }
   }

};

signed main(){

   int N, Q;
   cin>> N>> Q;
   SegmentTree st;
   while(Q--){
      int q; cin>> q;
      if(q==0){
         int s, t, x;
         cin>> s>> t>> x;
         st.update(s, t+1, x);
      }else{
         int s, t;
         cin>> s>> t;
         cout<< st.getmin(s, t+1)<< endl;
      }
   }

   return 0;
}