// Original C++ solution (slower):
#include <bits/stdc++.h>

using namespace std;

typedef pair<int,int> P;

typedef long long ll;

const int MAX_N = 1<<17;

const ll INF = INT_MAX;



/*

  RMQ and RUQ

  ?????????????°?????????????(RMQ)

  ????????????????????´??????(RUQ)

 */



class RMQ2{

public : 

  struct data{

    bool type; //0 - empty   , 1 - update

    ll value;

  };

  ll n,dat[2*MAX_N-1];

  data td[2*MAX_N-1];

  

  RMQ2(){

    n=MAX_N;

    memset(td,0,sizeof(td));

    for(int i=0;i<2*n-1;i++)dat[i]=INF;

  }

  RMQ2(int n_){

    n=1;

    while(n<n_)n*=2;

    memset(td,0,sizeof(td));

    for(int i=0;i<2*n-1;i++)dat[i]=INF;

  }

  

  //[a,b)?????????x????????´???update(a,b,x)

  ll update(int a,int b,int x,bool flg=true,int k=0,int l=0,int r=-1){

    if(r==-1) r=n;

    if(r<=a||b<=l)return flg? dat[k]:INF;

    if(a<=l&&r<=b){

      if(flg==true){

	td[k]=(data){1,x};

	dat[k]=x;

      }

      return dat[k];

    }

    

    if(td[k].type){

      dat[k*2+1]=dat[k*2+2]=td[k].value;

      td[k*2+1]=td[k*2+2]=(data){1,td[k].value};

      td[k].type=0;

    }

    

    ll vl=update(a,b,x,flg,k*2+1,l,(l+r)/2);

    ll vr=update(a,b,x,flg,k*2+2,(l+r)/2,r);

    if(flg==true)dat[k]=min(vl,vr);

    return min(vl,vr);

  }

  

  //[a,b)???????°????????????????find(a,b);

  ll find(int a,int b){return update(a,b,0,false);};

};





int main(){

  int q,n;

  cin>>n>>q;

  RMQ2 T(n);

  while(q--){

    int cmd,s,t,x;

    scanf("%d%d%d",&cmd,&s,&t);

    if(cmd==0)cin>>x,T.update(s,t+1,x);

    else cout <<T.find(s,t+1)<<endl;

  }

  return 0;

}

// Optimized solution to the same problem (faster):
#include <bits/stdc++.h>

using namespace std;

/*

  RMQ and RUQ

  区間の最小値を得る(RMQ)

  区間の値を変更する(RUQ)

 */



template<typename dtype>

class RMQ{

public : 

  dtype initValue; //範囲外の時に返す値

  

  struct data{

    bool type; //0 - empty   , 1 - update

    dtype value;

  };

  

  int n,n_;

  vector<dtype> dat;

  vector<data> td;

  int toMax;          //0 -> RangeMin 1->RangeMax;

  

  RMQ(){n=-1;}

  RMQ(int n_, dtype initValue, int toMax = 0):n_(n_),initValue(initValue),toMax(toMax){

    n=1;

    while(n<n_)n*=2;

    td.resize(2*n-1,(data){0,initValue});

    dat.resize(2*n-1,initValue);

  }



  inline dtype merge(dtype a, dtype b){return toMax? max(a, b):min(a, b);}

  

  

  dtype dfs(int a,int b,dtype x,bool flag,int k,int l,int r){

    if(r <= a || b <= l) return flag? dat[k]:initValue;

    if(a <= l && r <= b){

      if(flag == true){

        td[k]=(data){1,x};

        dat[k]=x;

      }

      return dat[k];

    }

    

    if(td[k].type){

      td[k].type = 0;

      dat[k*2+1] = dat[k*2+2] = td[k].value;

      td[k*2+1] = td[k*2+2] = (data){1,td[k].value};

    }



    dtype vl=dfs(a, b, x, flag, k*2+1, l, (l+r)/2);

    dtype vr=dfs(a, b, x, flag, k*2+2, (l+r)/2, r);

    return flag? (dat[k] = merge(vl, vr)):min(vl,vr);

  }

  

  //[l,r)の値をxに変更　update(l,r,x)

  void update(int l,int r,dtype x){

    assert(l <= r), assert(l <= n && r <= n), assert(l >= 0 && r >= 0);

    dfs(l, r, x, true, 0, 0, n);

  }

  

  //[l,r)の最小値を得る　find(l,r);

  dtype get(int l,int r){

    assert(l <= r), assert(l <= n && r <= n), assert(l >= 0 && r >= 0);

    return dfs(l, r, initValue , false, 0 , 0 ,n);

  }

};





int main(){

  int q,n;

  cin>>n>>q;

  typedef long long ll;

  RMQ <ll> T(n, INT_MAX);

  

  while(q--){

    int cmd,s,t,x;

    scanf("%d%d%d",&cmd,&s,&t);

    if(cmd==0)cin>>x,T.update(s,t+1,x);

    else cout <<T.get(s,t+1)<<endl;

  }

  return 0;

}




// Fastest known solution for this problem: