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 Rust (judge verdict: Accepted)

/* algebra */

pub trait Magma: Sized + Clone {
  fn op(&self, rhs: &Self) -> Self;
}

pub trait Associative: Magma {}

pub trait Unital: Magma {
  fn identity() -> Self;
}

pub trait Monoid: Magma + Associative + Unital {}

impl<T: Magma + Associative + Unital> Monoid for T {}

pub trait Effector: Monoid {
    type Target;
    fn effect(&self, t: &Self::Target) -> Self::Target;
}

use std::rc::Rc;

type Link<T, E> = Option<Rc<Node<T, E>>>;

struct Node<T: Monoid, E: Effector<Target=T>> {
    data: T,
    eff: E,
    left: Link<T, E>,
    right: Link<T, E>,
}

impl<T: Monoid, E: Effector<Target=T>> Node<T, E> {
    fn new(data: T) -> Self {
        Node { data: data, eff: E::identity(), left: None, right: None }
    }
    fn build(l: usize, r: usize) -> Self {
        if l + 1 >= r { Node::new(T::identity()) }
        else {
            Node {
                data: T::identity(),
                eff: E::identity(),
                left: Some(Rc::new(Node::build(l, (l + r) >> 1))),
                right: Some(Rc::new(Node::build((l + r) >> 1, r))),
            }
        }
    }

    fn effect_range(&self, a: usize, b: usize, new_eff: E, l: usize, r: usize, fold_eff: E) -> Self {
        if a <= l && r <= b {
            let eff = fold_eff.op(&new_eff);
            Node {
                data: eff.effect(&self.data),
                eff: self.eff.op(&eff),
                left: self.left.clone(),
                right: self.right.clone(),
            }
        }
        else if r <= a || b <= l {
            Node {
                data: fold_eff.effect(&self.data),
                eff: self.eff.op(&fold_eff),
                left: self.left.clone(),
                right: self.right.clone(),
            }
        }
        else {
            let left = Some(Rc::new(self.left.as_ref().unwrap().effect_range(a, b, new_eff.clone(), l, (l + r) >> 1, self.eff.op(&fold_eff))));
            let right = Some(Rc::new(self.right.as_ref().unwrap().effect_range(a, b, new_eff.clone(), (l + r) >> 1, r, self.eff.op(&fold_eff))));
            Node {
                data: match left.as_ref() { Some(n) => n.data.clone(), None => T::identity() }
                      .op(& match right.as_ref() { Some(n) => n.data.clone(), None => T::identity() }),
                eff: E::identity(),
                left: left,
                right: right,
            }
        }
    }

    fn fold(&self, a: usize, b: usize, l: usize, r: usize, eff: E) -> T {
        if a <= l && r <= b { eff.effect(&self.data.clone()) }
        else if r <= a || b <= l { T::identity() }
        else {
            match self.left.as_ref() { Some(n) => n.fold(a, b, l, (l + r) >> 1, self.eff.op(&eff)), None => T::identity() }
                .op(& match self.right.as_ref() { Some(n) => n.fold(a, b, (l + r) >> 1, r, self.eff.op(&eff)), None => T::identity() })
        }
    }
}

impl<T: Monoid, E: Effector<Target=T>> Drop for Node<T, E> {
    fn drop(&mut self) {
        if let Some(left) = self.left.take() {
            if let Ok(_) = Rc::try_unwrap(left) {}
        }
        if let Some(right) = self.right.take() {
            if let Ok(_) = Rc::try_unwrap(right) {}
        }
    }
}


pub struct PersistentLazySegmentTree<T: Monoid, E: Effector<Target=T>> {
    root: Node<T, E>,
    sz: usize,
}

impl<T: Monoid, E: Effector<Target=T>> PersistentLazySegmentTree<T, E> {
    pub fn new(n: usize) -> Self {
        Self { root: Node::build(0, n), sz: n }
    }
    pub fn effect_range(&self, l: usize, r: usize, eff: E) -> Self {
        Self { root: self.root.effect_range(l, r, eff, 0, self.sz, E::identity()), sz: self.sz }
    }
    pub fn fold(&self, l: usize, r: usize) -> T {
        self.root.fold(l, r, 0, self.sz, E::identity())
    }
}

use std::cmp::min;

#[derive(Clone, Debug)]
struct Mm(usize);

impl Magma for Mm {
    fn op(&self, right: &Self) -> Self { Mm(min(self.0, right.0)) }
}
impl Associative for Mm {}
impl Unital for Mm {
    fn identity() -> Self { Mm(2147483647) }
}

#[derive(Clone, Debug)]
struct Uq(Option<usize>);

impl Magma for Uq {
    fn op(&self, right: &Self) -> Self {
        if right.0.is_none() { self.clone() }
        else { right.clone() }
    }
}
impl Associative for Uq {}
impl Unital for Uq {
    fn identity() -> Self { Uq(None) }
}
impl Effector for Uq {
    type Target = Mm;
    fn effect(&self, t: &Self::Target) -> Self::Target {
        match self.0 {
            Some(u) => Mm(u),
            None => t.clone(),
        }
    }
}

fn main() {
    let mut s = String::new();
    std::io::stdin().read_line(&mut s).unwrap();
    let v:Vec<usize> = s.trim().split_whitespace()
        .map(|e|e.parse().unwrap()).collect();
    let (n,m) = (v[0] , v[1]);
    let mut seg = PersistentLazySegmentTree::new(n);
    for _ in 0..m {
        let mut t = String::new();
        std::io::stdin().read_line(&mut t).unwrap();
        let x:Vec<usize> = t.trim().split_whitespace()
            .map(|e|e.parse().unwrap()).collect();
        match x[0] {
            0 => {
                seg = seg.effect_range(x[1], x[2] + 1, Uq(Some(x[3] as usize)));
            }
            _ => {
                println!("{}", seg.fold(x[1], x[2] + 1).0);
            }
        }
    }
}