/*
参考
https://ei1333.github.io/luzhiled/snippets/structure/segment-tree.html

https://firiexp.github.io/library/library/lazysegtree.html

https://smijake3.hatenablog.com/entry/2018/11/03/100133#%E9%81%85%E5%BB%B6%E8%A9%95%E4%BE%A1%E3%82%BB%E3%82%B0%E3%83%A1%E3%83%B3%E3%83%88%E6%9C%A8%E3%81%AE%E6%A6%82%E8%A6%81
verify:
http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DSL_2_F
*/
#pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
using namespace std;

#define INF 1LL << 55
#define MAX (1LL << 31) -1
#define MOD 1000000007
typedef long long ll;
typedef pair<ll,ll> P;
//typedef pair<pair<int,int>,int> p;
#define bit(n, k) ((n >> k) & 1) /*nのk bit目*/
#define rad_to_deg(rad) (((rad) / 2 / M_PI) * 360)
struct edge{ll to,cost,val;};
template<class T,class U>bool chmin(T&a,const U&b){if(a<=b)return false;a=b;return true;}
template<class T,class U>bool chmax(T&a,const U&b){if(a>=b)return false;a=b;return true;}
//__builtin_popcount(S);
//C.erase(unique(C.begin(),C.end()),C.end());
//#define int ll
int dx[]={1,-1,0,0},dy[]={0,0,-1,1};
//#define F function<T(T,T)>

template<class T,class L,class F,class G,class H>
struct LazySegmentTree{
    //データ
    int sz;
    int height;
    vector<T> seg;
    vector<L> lazy;
    const T sut;
    const L lut;
    const F f;
    const G g;
    const H h;

    LazySegmentTree(int n,const T sut,const L lut,const F &f,const G &g,const H &h):sut(sut),lut(lut),f(f),g(g),h(h){
        sz=1;
        height=0;
        while(sz<n) sz<<=1,height++;
        seg.assign((sz<<1),sut);
        lazy.assign((sz<<1),lut);        
    }

    inline void set(int k,const T &x){
        seg[k+sz]=x;
    }
    inline void build(){
        for(int k=sz-1;k>0;k--){
            seg[k]=f(seg[(k<<1)],seg[(k<<1)+1]);
        }
    }
    inline T reflect(int k){
        return (lazy[k]==lut) ? seg[k]:g(seg[k],lazy[k]);
    }
    //子にlazyを伝える(updateで丸々収まる所を更新した尻ぬぐい)
    //lazy[k]とlazy[2*k]が違った場合,lazy[k]の方が後に更新されたもの
    inline void propagate(int k){
        if(lazy[k]!=lut){
            lazy[(k<<1)]=h(lazy[(k<<1)],lazy[k]);
            lazy[(k<<1)+1]=h(lazy[(k<<1)+1],lazy[k]);
            seg[k]=reflect(k);
            lazy[k]=lut;
        }
    }
    //ボトムアップで更新していく
    inline void recalc(int k){
        while(k>>=1) seg[k]=f(reflect((k<<1)),reflect((k<<1)+1));
    }
    //トップダウンで更新していく(これでseg[k]が正しい値になる)
    inline void thrust(int k){
        for(int i=height;i>0;i--) propagate(k>>i);
    }
    //[a:b)
    void update(int a,int b,const L &x){
        //トップダウンでlazy[i]!=lutのものを更新
        thrust(a+=sz);
        thrust(b+=sz-1);
        //丸々収まるところを更新
        for(int l=a,r=b+1;l<r;l>>=1,r>>=1){
            if(l&1) lazy[l]=h(lazy[l],x),l++;
            if(r&1) --r,lazy[r]=h(lazy[r],x);
        }
        //ボトムアップで新しく更新
        recalc(a);
        recalc(b);
    }

    //[a:b)
    T query(int a,int b){
        //トップダウンで関係あってlazy[i]!=lutのものを更新
        thrust(a+=sz);
        thrust(b+=sz-1);
        //更新した後は普通のセグ木と同じ
        T l=sut,r=sut;
        for(a,b+=1;a<b;a>>=1,b>>=1){
            if(a&1) l=f(l,reflect(a++));
            if(b&1) r=f(reflect(--b),r);
        }
        return f(l,r);
    }
    //セグ木と違い、log(n)かかる
    T operator[](const int k){
        return query(k,k+1);
    }

};

//[](int a,int b){return min(a,b);}

signed main(){
    ios::sync_with_stdio(false);
	cin.tie(0);
    int n,q;
    cin>>n>>q;
    auto f=[](int a,int b){return min(a,b);};
    auto g=[](int a,int b){return b;};
    auto h=[](int a,int b){return b;};
    LazySegmentTree<int,int,decltype(f),decltype(g),decltype(h)> l(n,MAX,-1,f,g,h);
    while(q--){
        int a;
        cin>>a;
        if(a==0){
            int s,t,x;
            cin>>s>>t>>x;
            l.update(s,t+1,x);
        }else{
            int s,t;
            cin>>s>>t;
            cout<<l.query(s,t+1)<<"\n";
        }
    }

}


Measured memory_bytes: 4944