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.Numerics;
using static System.Console;
using static System.Math;

class Program
{
    static void Main()
    {
        SetOut(new System.IO.StreamWriter(OpenStandardOutput()) { AutoFlush = false });
        var N = FastIO.Int();
        var Q = FastIO.Int();
        var d = new AVLTree<int, int>(Min, (x, y, s) => y == int.MaxValue ? x : y, (x, y) => y == int.MaxValue ? x : y, int.MaxValue, int.MaxValue);
        d.Init(N);
        for (int i = 0; i < Q; i++)
        {
            if (FastIO.Int() == 0)
            {
                var s = FastIO.Int();
                var t = FastIO.Int() + 1;
                var x = FastIO.Int();
                d.Update(s, t, x);
            }
            else
            {
                var s = FastIO.Int();
                var t = FastIO.Int() + 1;
                WriteLine(d.Query(s, t));
            }
        }
        Out.Flush();
    }
}

public static class FastIO
{
    static System.IO.Stream str = System.Console.OpenStandardInput();
    const int size = 1024;
    static byte[] buffer = new byte[size];
    static int ptr;
    static int len;

    static byte Read()
    {
        if (ptr == len)
        {
            len = str.Read(buffer, 0, size);
            if (len == 0) return 0;
            ptr = 0;
        }
        return buffer[ptr++];
    }

    public static int Int()
    {
        var c = Read();
        while (c < 0x21)
        {
            c = Read();
        }
        var n = false;
        if (c == '-')
        {
            n = true;
            c = Read();
        }
        var ret = 0;
        while (c > 0x20)
        {
            ret = ret * 10 + c - '0';
            c = Read();
        }
        return n ? -ret : ret;
    }

    public static long Long()
    {
        var c = Read();
        while (c < 0x21)
        {
            c = Read();
        }
        var n = false;
        if (c == '-')
        {
            n = true;
            c = Read();
        }
        var ret = 0L;
        while (c > 0x20)
        {
            ret = ret * 10 + c - '0';
            c = Read();
        }
        return n ? -ret : ret;
    }
}

public class AVLTree<T, E> where E : IEquatable<E>
{
    class Node
    {
        public T value;
        public int height;
        public int size;
        public T acc;
        public E lazy;
        public bool rev;
        public Node l;
        public Node r;
    }

    Node root;
    Func<T, T, T> F;
    Func<T, E, int, T> G;
    Func<E, E, E> H;
    T TI;
    E EI;
    int count;
    public int Count => count;

    public AVLTree(Func<T, T, T> f, Func<T, E, int, T> g, Func<E, E, E> h, T ti, E ei)
    {
        F = f;
        G = g;
        H = h;
        TI = ti;
        EI = ei;
    }

    public void Init(int length)
    {
        DFSL(ref root, 0, length);
        count = length;
    }

    void DFSL(ref Node p, int l, int r)
    {
        if (l == r) return;
        var k = (l + r) / 2;
        p = new Node { value = TI, size = r - l, acc = TI, lazy = EI };//height=Log2(r-l)+1
        DFSL(ref p.l, l, k);
        DFSL(ref p.r, k + 1, r);
        UpdateHeight(p);
    }

    int Height(Node t) => t != null ? t.height : 0;

    void UpdateHeight(Node t) => t.height = Math.Max(Height(t.l), Height(t.r)) + 1;

    int Size(Node t) => t != null ? t.size : 0;

    void UpdateSize(Node t) => t.size = Size(t.l) + Size(t.r) + 1;

    T Acc(Node t) => t != null ? t.acc : TI;

    void UpdateAcc(Node t) => t.acc = F(F(Acc(t.l), t.value), Acc(t.r));

    void PushUp(Node t)
    {
        UpdateHeight(t);
        UpdateAcc(t);
        UpdateSize(t);
    }

    void Swap(ref Node l, ref Node r)
    {
        var t = l;
        l = r;
        r = t;
    }

    void PushDown(Node t)
    {
        if (t.rev)
        {
            t.rev = false;
            Swap(ref t.l, ref t.r);
            if (t.l != null) t.l.rev = !t.l.rev;
            if (t.r != null) t.r.rev = !t.r.rev;
        }
        if (!t.lazy.Equals(EI))
        {
            if (t.l != null)
            {
                t.l.lazy = H(t.l.lazy, t.lazy);
                t.l.acc = G(t.l.acc, t.lazy, Size(t.l));
            }
            if (t.r != null)
            {
                t.r.lazy = H(t.r.lazy, t.lazy);
                t.r.acc = G(t.r.acc, t.lazy, Size(t.r));
            }
            t.value = G(t.value, t.lazy, 1);
            t.lazy = EI;
        }
    }

    void RotateR(ref Node t)
    {
        var n = t.l;
        t.l = t.l.r;
        n.r = t;
        t = n;
        PushUp(t.r);
        PushUp(t);
    }

    void RotateL(ref Node t)
    {
        var n = t.r;
        t.r = t.r.l;
        n.l = t;
        t = n;
        PushUp(t.l);
        PushUp(t);
    }

    void Balance(ref Node t)
    {
        var b = Height(t.l) - Height(t.r);
        if (b == 2)
        {
            if (Height(t.l.l) - Height(t.l.r) == -1)
            {
                PushDown(t.l);
                PushDown(t.l.r);
                RotateL(ref t.l);
                RotateR(ref t);
            }
            else
            {
                PushDown(t.l);
                RotateR(ref t);
            }
        }
        else if (b == -2)
        {
            if (Height(t.r.l) - Height(t.r.r) == 1)
            {
                PushDown(t.r);
                PushDown(t.r.l);
                RotateR(ref t.r);
                RotateL(ref t);
            }
            else
            {
                PushDown(t.r);
                RotateL(ref t);
            }
        }
        else PushUp(t);
    }

    void Cut(Node t)
    {
        t.l = t.r = null;
        t.size = 1;
        t.height = 1;
        t.acc = t.value;
    }

    void SplitMin(Node t, out Node m, out Node r)
    {
        PushDown(t);
        if (t.l == null)
        {
            r = t.r;
            m = t;
            Cut(m);
        }
        else
        {
            SplitMin(t.l, out m, out r);
            t.l = r;
            r = t;
            Balance(ref r);
        }
    }

    void SplitMax(Node t, out Node l, out Node m)
    {
        PushDown(t);
        if (t.r == null)
        {
            l = t.l;
            m = t;
            Cut(m);
        }
        else
        {
            SplitMax(t.r, out l, out m);
            t.r = l;
            l = t;
            Balance(ref l);
        }
    }

    Node MergeWithRoot(Node l, Node m, Node r)
    {
        var b = Height(l) - Height(r);
        if (-1 <= b && b <= 1)
        {
            m.l = l;
            m.r = r;
            PushUp(m);
            return m;
        }
        else if (b > 0)
        {
            PushDown(l);
            l.r = MergeWithRoot(l.r, m, r);
            Balance(ref l);
            return l;
        }
        else
        {
            PushDown(r);
            r.l = MergeWithRoot(l, m, r.l);
            Balance(ref r);
            return r;
        }
    }

    void Merge(out Node t, Node l, Node r)
    {
        if (l == null || r == null)
        {
            t = l ?? r;
            return;
        }
        if (l.height < r.height)
        {
            Node m;
            SplitMax(l, out l, out m);
            t = MergeWithRoot(l, m, r);
        }
        else
        {
            Node m;
            SplitMin(r, out m, out r);
            t = MergeWithRoot(l, m, r);
        }
    }

    void Split(Node t, int k, out Node l, out Node r)
    {
        if (t == null)
        {
            l = r = null;
            return;
        }
        PushDown(t);
        var p = Size(t.l);
        if (k == p)
        {
            l = t.l;
            r = t.r;
            Cut(t);
            Merge(out r, t, r);
            return;
        }
        if (k < p)
        {
            Split(t.l, k, out l, out r);
            var tr = t.r;
            Cut(t);
            r = MergeWithRoot(r, t, tr);
        }
        else
        {
            Split(t.r, k - p - 1, out l, out r);
            var tl = t.l;
            Cut(t);
            l = MergeWithRoot(tl, t, l);
        }
    }

    public void Update(int l, int r, E v)
    {
        if (l >= r) return;
        Node t1, t2, t3;
        Split(root, r, out t2, out t3);
        Split(t2, l, out t1, out t2);
        t2.lazy = H(t2.lazy, v);
        t2.acc = G(t2.acc, v, Size(t2));
        Merge(out t2, t1, t2);
        Merge(out root, t2, t3);
    }

    public T Query(int l, int r)
    {
        if (l == r) return TI;
        Node t1, t2, t3;
        Split(root, r, out t2, out t3);
        Split(t2, l, out t1, out t2);
        var ret = t2.acc;
        Merge(out t2, t1, t2);
        Merge(out root, t2, t3);
        return ret;
    }
}