Problem:
Range Update Query (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(i): output the value of ai.

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 i

The first digit represents the type of the query. '0' denotes update(s, t, x) and '1' denotes find(i).

Output

For each find operation, print the value.

Constraints

1 ≤ n ≤ 100000

1 ≤ q ≤ 100000

0 ≤ s ≤ t < n

0 ≤ i < n

0 ≤ x < 231−1

Sample Input 1

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

Sample Output 1

1
3

Sample Input 2

1 3
1 0
0 0 0 5
1 0

Sample Output 2

2147483647
5

Solution in Rust (judge verdict: Accepted)

use std::cmp::*;
use std::collections::*;
use std::fmt::Debug;
use std::io::BufRead;
use std::io::{stdin, Read};
use std::ops::{Add, Sub};
use std::str::FromStr;

#[derive(Eq, PartialEq, Clone, Debug)]
pub struct Rev<T>(pub T);

impl<T: PartialOrd> PartialOrd for Rev<T> {
    fn partial_cmp(&self, other: &Rev<T>) -> Option<Ordering> {
        other.0.partial_cmp(&self.0)
    }
}

impl<T: Ord> Ord for Rev<T> {
    fn cmp(&self, other: &Rev<T>) -> Ordering {
        other.0.cmp(&self.0)
    }
}

fn read<T: FromStr>() -> T {
    let stdin = stdin();
    let stdin = stdin.lock();
    let token: String = stdin
        .bytes()
        .map(|c| c.expect("failed to read char") as char)
        .skip_while(|c| c.is_whitespace())
        .take_while(|c| !c.is_whitespace())
        .collect();

    token.parse().ok().expect("failed to parse token")
}

macro_rules! read {
    (($($t:tt),*)) => {
        ( $(read!($t)),* )
    };
    ([[$t:tt; $len1:expr]; $len2:expr]) => {
        (0..$len2).map(|_| read!([$t; $len1])).collect::<Vec<_>>()
    };

    ([$t:tt; $len:expr]) => {
        (0..$len).map(|_| read!($t)).collect::<Vec<_>>()
    };

    (chars) => {
        read!(String).chars().collect::<Vec<char>>()
    };

    (usize1) => {
        read!(usize) - 1
    };

    ($t:ty) => {{
        let stdin = stdin();
        let stdin = stdin.lock();
        let token: String = stdin
            .bytes()
            .map(|c| c.unwrap() as char)
            .skip_while(|c| c.is_whitespace())
            .take_while(|c| !c.is_whitespace())
            .collect();

        token.parse::<$t>().unwrap()
    }};
}

macro_rules! input {
    (mut $name:ident: $t:tt, $($r:tt)*) => {
        let mut $name = read!($t);
        $(println!("{}", stringify!($r));)*
        input!($($r)*);
    };

    (mut $name:ident: $t:tt) => {
        let mut $name = read!($t);
    };

    ($name:ident: $t:tt, $($r:tt)*) => {
        let $name = read!($t);
        input!($($r)*);
    };

    ($name:ident: $t:tt) => {
        let $name = read!($t);
    };
}

trait VecExt {
    fn cumulation(&self) -> Vec<i64>;
    fn cumulation_query(&self, a: usize, b: usize) -> i64;
}

impl VecExt for Vec<i64> {
    fn cumulation(&self) -> Vec<i64> {
        let mut vec = vec![0; self.len() + 1];
        for i in 0..self.len() {
            vec[i + 1] = self[i] + vec[i];
        }
        return vec;
    }

    fn cumulation_query(&self, left: usize, right: usize) -> i64 {
        return self[right] - self[left];
    }
}

pub trait Monoid {
    type T: Copy + Clone + std::fmt::Debug + PartialOrd + std::fmt::Display;
    fn op(lhs: &Self::T, rhs: &Self::T) -> Self::T;
    fn identity() -> Self::T;
}

pub trait OperatorMonoid {
    type T;
    type U: Copy + Clone + std::fmt::Debug + PartialOrd;
    fn op1(lhs: &Self::U, rhs: &Self::U) -> Self::U;
    fn op2(lhs: &Self::T, rhs: &Self::U, len: &usize) -> Self::T;
    fn identity() -> Self::U;
}

#[derive(Clone)]
struct Min {}

impl Monoid for Min {
    type T = i64;

    fn identity() -> Self::T {
        return (1 << 31) - 1 
    }

    fn op(lhs: &Self::T, rhs: &Self::T) -> Self::T {
        return std::cmp::min(*lhs, *rhs);
    }
}

#[derive(Clone)]
struct OperatorMin {}

impl OperatorMonoid for OperatorMin {
    type T = i64;
    type U = Option<i64>;

    fn identity() -> Self::U {
        return None;
    }

    fn op1(lhs: &Self::U, rhs: &Self::U) -> Self::U {
        return *rhs
    }

    fn op2(lhs: &Self::T, rhs: &Self::U, _: &usize) -> Self::T {
        if rhs.is_some() {
            (*rhs).unwrap()
        } else {
            *lhs
        }
    }
}

#[derive(Debug)]
pub struct LazySegmentTree<M: Monoid, O: OperatorMonoid<T = M::T>> {
    n: usize,
    size: usize,
    data: Vec<M::T>,
    lazy: Vec<O::U>,
}

impl<M: Monoid, O: OperatorMonoid<T = M::T>> LazySegmentTree<M, O> {
    pub fn new(n: usize) -> LazySegmentTree<M, O> {
        let mut size = 1;
        while size < n {
            size *= 2;
        }

        LazySegmentTree {
            n: n,
            size: size,
            data: vec![M::identity(); size * 2],
            lazy: vec![O::identity(); size * 2],
        }
    }

    pub fn set(&mut self, k: usize, v: M::T) {
        self.data[k + self.size] = v;
    }

    pub fn build(&mut self) {
        for k in (1..self.size - 1).rev() {
            self.data[k] = M::op(&self.data[k * 2], &self.data[k * 2 + 1]);
        }
    }

    pub fn propagate(&mut self, k: usize, len: usize) {
        if self.lazy[k] != O::identity() {
            if k < self.size {
                self.lazy[2 * k + 0] = O::op1(&self.lazy[2 * k + 0], &self.lazy[k]);
                self.lazy[2 * k + 1] = O::op1(&self.lazy[2 * k + 1], &self.lazy[k]);
            }
            self.data[k] = O::op2(&self.data[k], &self.lazy[k], &len);
            self.lazy[k] = O::identity();
        }
    }

    pub fn _update(&mut self, a: usize, b: usize, x: O::U, k: usize, l: usize, r: usize) {
        self.propagate(k, r - l);
        if r <= a || b <= l {
            return;
        } else if a <= l && r <= b {
            self.lazy[k] = O::op1(&self.lazy[k], &x);
            self.propagate(k, r - l);
        } else {
            self._update(a, b, x, 2 * k + 0, l, (l + r) >> 1);
            self._update(a, b, x, 2 * k + 1, (l + r) >> 1, r);
            self.data[k] = M::op(&self.data[2 * k + 0], &self.data[2 * k + 1]);
        }
    }

    pub fn update(&mut self, a: usize, b: usize, x: O::U) {
        let sz = self.size;
        self._update(a, b, x, 1, 0, sz);
    }

    fn _query(&mut self, a: usize, b: usize, k: usize, l: usize, r: usize) -> M::T {
        self.propagate(k, r - l);
        if r <= a || b <= l {
            return M::identity();
        } else if a <= l && r <= b {
            return self.data[k];
        } else {
            return M::op(
                &self._query(a, b, 2 * k + 0, l, (l + r) >> 1),
                &self._query(a, b, 2 * k + 1, (l + r) >> 1, r),
            );
        }
    }

    pub fn query(&mut self, a: usize, b: usize) -> M::T {
        let sz = self.size;
        return self._query(a, b, 1, 0, sz);
    }

    pub fn debug(&self) {
        for i in 0..self.n {
            print!("{} ", self.data[i + self.size]);
        }
        println!();
    }
}

fn main() {
    input!(n: usize, q: usize);
    let mut seg: LazySegmentTree<Min, OperatorMin> = LazySegmentTree::new(n);
    for _ in 0..q {
        input!(com: usize);
        if com == 0 {
            input!(s: usize, t: usize, x: i64);
            seg.update(s, t + 1, Some(x));
        } else {
            input!(i: usize);
            println!("{}", seg.query(i, i + 1));
        }
    }
}