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 <algorithm>
#include <stdio.h>
#include <vector>
#include <math.h>
#include <iostream>
using namespace std;

#define INF      2147483647LL
// #define NUL      2147483647LL
#define NUL     -1LL
typedef long long int llong;

llong n_array;
llong queries;
vector<llong> D, Lazy;

void printDL();

void lazyEv(llong k, llong l, llong r){
  if( Lazy[k] == NUL ){
    return;
  }
  D[k] = Lazy[k];
  // if it is not leaf
  if( r - l > 1 ){
    Lazy[2*k+1] = Lazy[k];
    Lazy[2*k+2] = Lazy[k];
  }
  Lazy[k] = NUL;
}

void init(llong reqsz){
  n_array = 1;
  while( n_array < reqsz ){
    n_array *= 2;
  }
  D.resize(2*n_array-1, 0);
  Lazy.resize(2*n_array-1, NUL);

  for( llong i = 0 ; i < reqsz ; i++ ){
    D[i+n_array-1] = INF; // initialize the leaves
  }
  for( llong i = n_array - 2 ; i >= 0 ; i--){
    D[i] = min(D[i*2+1] ,D[i*2+2]); // first update segment tree
  }
}

void updateRange(llong a, llong b, llong x, llong k=0, llong l=0, llong r=-1){
  if( r < 0 ){
    r = n_array;
  }

  lazyEv(k, l, r);
  if( b <= l || r <= a){  // case 1
    return;
  }else if( a <= l && r <= b ){ // case 2
    Lazy[k] = x;
    lazyEv(k, l, r);
  }else{ // case 3
    updateRange(a, b, x, 2*k+1, l, (l+r)/2);
    updateRange(a, b, x, 2*k+2, (l+r)/2, r);
    D[k] = min(D[2*k+1], D[2*k+2]);
  }

}

llong find(llong a, llong b, llong k=0, llong l=0 , llong r=-1){
  if( r < 0 ){
    r = n_array;
  }
  lazyEv(k, l, r);
  if( b <= l || r <= a){  // case 1
    return INF;
  }else if( a <= l && r <= b ){ // case 2
    return D[k];
  }else{ // case 3
    llong vl = find(a, b, 2*k+1, l, (l+r)/2);
    llong vr = find(a, b, 2*k+2, (l+r)/2, r);
    return min(vl,vr);
  }
}

void printDL(){ // For debug
  llong i = 0;
  llong j = 0;
  for (const auto& e : D) {
     printf("D[%lld]=" ,i); i++;
     std::cout << e << std::endl;
  }
  for (const auto& e : Lazy) {
     printf("Lazy[%lld]=" ,j); j++;
     std::cout << e << std::endl;
  }
}

int main(){
  llong reqsz;
  scanf("%lld %lld" ,&reqsz ,&queries);
  init(reqsz);
  for(llong i = 0 ; i < queries ; i++){
    llong com;
    scanf("%lld" ,&com ); 
    if( com== 0){
      llong s, t, x;
      scanf("%lld %lld %lld" ,&s ,&t ,&x );
      updateRange(s, t+1, x);
    }else{
      llong s, t;
      scanf("%lld %lld" ,&s ,&t );
      llong result = find(s, t+1);
      printf("%lld\n" ,result);
    }
  }

  return 0;
}