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)

using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Globalization;
using System.Diagnostics;
using Pair = System.Collections.Generic.KeyValuePair<int, int>;


// https://pekempey.github.io/lazy_propagation_segment_tree/lazy_propagation_segment_tree.html

class Program
{
    static void Main()
    {
        Console.SetOut(new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = false });
        new Program().Solve();
        Console.Out.Flush();
    }
    Scanner cin = new Scanner();


    void Solve()
    {
        int n_ = cin.Nextint;
        int q = cin.Nextint;

        int n = 1;
        while (n < n_) n *= 2;

        var M = new RMQ_2(n, int.MaxValue);


        for (int i = 0; i < q; i++)
        {
            if (cin.Nextint == 0)
            {
                int s = cin.Nextint, t = cin.Nextint, x = cin.Nextint;
                M.Update(s, t + 1, x, 0, 0, n);
            }
            else
            {
                int s = cin.Nextint, t = cin.Nextint;
                Console.WriteLine(M.Find(s, t + 1, 0, 0, n));
            }
        }
    }

}

class RMQ_2
{
    int n;
    int[] mini;
    int[] lazy;


    public RMQ_2(int m, int t)
    {
        n = m;
        mini = Enumerable.Repeat(t, 2 * n - 1).ToArray();
        lazy = Enumerable.Repeat(-1, 2 * n - 1).ToArray();
    }

    //[a, b) update
    public void Update(int a, int b, int x, int k, int l, int r) //ue-kara
    {
        if (r <= a || b <= l) return;
        if (a <= l && r <= b) Setlazy(k, x);

        else
        {
            Push(k); //sita-he
            Update(a, b, x, k * 2 + 1, l, (l + r) / 2);
            Update(a, b, x, k * 2 + 2, (l + r) / 2, r);

            fix(k); //ue-he
        }
    }
    void fix(int k)
    {
        mini[k] = Math.Min(mini[k * 2 + 1], mini[k * 2 + 2]);
    }
 

    //[a, b) Min
    public int Find(int a, int b, int k, int l, int r) //ue-kara
    {
        if (r <= a || b <= l) return int.MaxValue;
        if (a <= l && r <= b) return mini[k];

        Push(k); //sita-he
        int vl = Find(a, b, k * 2 + 1, l, (l + r) / 2);
        int vr = Find(a, b, k * 2 + 2, (l + r) / 2, r);
        return Math.Min(vl, vr);
    }

    void Push(int k)//?????¶
    {
        if (lazy[k] == -1) return;

        Setlazy(k * 2 + 1, lazy[k]);
        Setlazy(k * 2 + 2, lazy[k]);

        lazy[k] = -1;

    }
    void Setlazy(int k, int v)//?????¶
    {
        lazy[k] = v;
        mini[k] = v;
    }

}

class Scanner
{
    string[] s; int i;
    char[] cs = new char[] { ' ' };
    public Scanner() { s = new string[0]; i = 0; }
    public string[] Scan { get { return Console.ReadLine().Split(); } }
    public int[] Scanint { get { return Array.ConvertAll(Scan, int.Parse); } }
    public long[] Scanlong { get { return Array.ConvertAll(Scan, long.Parse); } }
    public double[] Scandouble { get { return Array.ConvertAll(Scan, double.Parse); } }
    public string Next
    {
        get
        {
            if (i < s.Length) return s[i++];
            string st = Console.ReadLine();
            while (st == "") st = Console.ReadLine();
            s = st.Split(cs, StringSplitOptions.RemoveEmptyEntries);
            i = 0;
            return Next;
        }
    }
    public int Nextint { get { return int.Parse(Next); } }
    public long Nextlong { get { return long.Parse(Next); } }
    public double Nextdouble { get { return double.Parse(Next); } }
}