Problem:
RMQ and RUQ

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.

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.

Constraints

1 ≤ n ≤ 100000

1 ≤ q ≤ 100000

0 ≤ s ≤ t < n

0 ≤ x < 231−1

Sample Input 1

3 5
0 0 1 1
0 1 2 3
0 2 2 2
1 0 2
1 1 2

Sample Output 1

1
2

Sample Input 2

1 3
1 0 0
0 0 0 5
1 0 0

Sample Output 2

2147483647
5

Solution in C++ (judge verdict: Accepted)

/* RMQ：[0,n-1] について、区間ごとの最小値を管理する構造体
    set(int i, T x), build(): i番目の要素をxにセット。まとめてセグ木を構築する。O(n)
    update(i,x): i 番目の要素を x に更新。O(log(n))
    query(a,b): [a,b) での最小の要素を取得。O(log(n))
    find_rightest(a,b,x): [a,b) で x以下の要素を持つ最右位置を求める。O(log(n))
    find_leftest(a,b,x): [a,b) で x以下の要素を持つ最左位置を求める。O(log(n))
*/
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define rep(i, n) for (int i = 0; i < n; i++)

/* RMQ：[0,n-1] について、区間ごとの最小値を管理する構造体
    update(a,b,x): 区間[a,b) の要素を x に更新。O(log(n))
    query(a,b): [a,b) での最小の要素を取得。O(log(n))
*/
template <typename T>
struct RMQ
{
    ll INF = pow(2, 31) - 1;
    int n;
    vector<T> dat, lazy;
    RMQ(int n_) : n(), dat(n_ * 4, INF), lazy(n_ * 4, INF)
    {
        int x = 1;
        while (n_ > x)
            x *= 2;
        n = x;
    }

    /* lazy eval */
    void eval(int k)
    {
        if (lazy[k] == INF)
            return; // 更新するものが無ければ終了
        if (k < n - 1)
        { // 葉でなければ子に伝搬
            lazy[k * 2 + 1] = lazy[k];
            lazy[k * 2 + 2] = lazy[k];
        }
        // 自身を更新
        dat[k] = lazy[k];
        lazy[k] = INF;
    }

    void update(int a, int b, T x, int k, int l, int r)
    {
        eval(k);
        if (a <= l && r <= b)
        { // 完全に内側の時
            lazy[k] = x;
            eval(k);
        }
        else if (a < r && l < b)
        {                                               // 一部区間が被る時
            update(a, b, x, k * 2 + 1, l, (l + r) / 2); // 左の子
            update(a, b, x, k * 2 + 2, (l + r) / 2, r); // 右の子
            dat[k] = min(dat[k * 2 + 1], dat[k * 2 + 2]);
        }
    }
    void update(int a, int b, T x) { update(a, b, x, 0, 0, n); }

    T query_sub(int a, int b, int k, int l, int r)
    {
        eval(k);
        if (r <= a || b <= l)
        { // 完全に外側の時
            return INF;
        }
        else if (a <= l && r <= b)
        { // 完全に内側の時
            return dat[k];
        }
        else
        { // 一部区間が被る時
            T vl = query_sub(a, b, k * 2 + 1, l, (l + r) / 2);
            T vr = query_sub(a, b, k * 2 + 2, (l + r) / 2, r);
            return min(vl, vr);
        }
    }
    T query(int a, int b) { return query_sub(a, b, 0, 0, n); }

    /* debug */
    inline T operator[](int a) { return query(a, a + 1); }
    void print()
    {
        for (int i = 0; i < 2 * n - 1; ++i)
        {
            cout << (*this)[i];
            if (i != n)
                cout << ",";
        }
        cout << endl;
    }
};
int main()
{
    ll n, q;
    vector<ll> A;

    cin >> n >> q;
    RMQ<ll> data(n);
    rep(i, q)
    {
        int a, b, c;
        cin >> a >> b >> c;
        c++;
        if (a == 1)
        {
            cout << data.query(b, c) << endl;
        }
        else
        {
            ll x;
            cin >> x;
            data.update(b, c, x);
        }
    }
}