Problem:
RMQ and RUQ Write a program which manipulates a sequence A = { a 0 , a 1 , . . .  , a n−1 } with the following operations:  update(s, t, x) : change a s , a s+1 , ..., a t to x .  find(s, t) : report the minimum element in a s , a s+1 , ..., a t .  Note that the initial values of a i ( i = 0, 1, . . .  , n−1 ) are 2 31 -1. Input  n  q  query 1  query 2 : query q  In the first line, n (the number of elements in A ) and q (the number of queries) are given. Then, i th query query i 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 < 2 31 −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 (Python):
import sys
write = sys.stdout.write


class LazySegmentTree():
    def __init__(self,
                 array,
                 ti,
                 ei,
                 f=lambda: None,
                 g=lambda: None,
                 h=lambda: None):
        """
        Parameters
        ----------
        array : list
            to construct segment tree from
        ti : T
            identity element of T
        ei : E
            identity element of E
        f : func
            binary operation of the monoid
            T x T -> T
            T is dat
        g : func
            binary operation of the monoid
            T x E -> T
            T is dat, E is laz
        h : func
            binary operation of the monoid
            E x E -> T
            E is laz
        """
        self.f = f
        self.g = g
        self.h = h
        self.ti = ti
        self.ei = ei
        self.LV = LV = (len(array) - 1).bit_length()
        self.N0 = N0 = 2**LV
        self.data = data = [ti] * N0 + array + [ti] * (N0 - len(array))
        self.lazy = [ei] * (2 * N0)
        '''
        for i in range(N0 - 1, 0, -1):  
            data[i] = f(data[i << 1], data[i << 1 | 1])
        '''
        for i in range(N0 - 1, 0, -1):  
            data[i] = data[i << 1] if data[i << 1] < data[i << 1
                                                          | 1] else data[i << 1
                                                                         | 1]

    def gindex(self, l, r):
        LV = self.LV
        N0 = self.N0
        L = (l + N0) >> 1
        R = (r + N0) >> 1
        lc = 0 if l & 1 else (L & -L).bit_length()
        rc = 0 if r & 1 else (R & -R).bit_length()
        ret = []
        for i in range(LV):
            if rc <= i:
                ret += [R]
            if L < R and lc <= i:
                ret += [L]
            L >>= 1
            R >>= 1
        return ret

    def propagates(self, *ids):
        data = self.data
        lazy = self.lazy
        for i in reversed(ids):
            v = lazy[i - 1]
            if v is ei:
                continue
            '''
            data[2 * i - 1] = g(data[2 * i - 1], v)
            data[2 * i] = g(data[2 * i], v)
            lazy[2 * i - 1] = h(lazy[2 * i - 1], v)
            lazy[2 * i] = h(lazy[2 * i], v)
            '''
            data[2 * i - 1] = v
            data[2 * i] = v
            lazy[2 * i - 1] = v
            lazy[2 * i] = v

            lazy[i - 1] = ei

    def update(self, l, r, x):
        data = self.data
        lazy = self.lazy
        N0 = self.N0
        *ids, = self.gindex(l, r)
        self.propagates(*ids)
        L = N0 + l
        R = N0 + r
        while L < R:
            '''
            if R & 1:
                R -= 1
                lazy[R - 1] = h(lazy[R - 1], x)
                data[R - 1] = g(data[R - 1], x)
            if L & 1:
                lazy[L - 1] = h(lazy[L - 1], x)
                data[L - 1] = g(data[L - 1], x)
                L += 1
            '''
            if R & 1:
                R -= 1
                lazy[R - 1] = x
                data[R - 1] = x
            if L & 1:
                lazy[L - 1] = x
                data[L - 1] = x
                L += 1
            L >>= 1
            R >>= 1
        for i in ids:
            '''
            data[i - 1] = f(data[2 * i - 1], data[2 * i])
            '''
            data[i - 1] = data[
                2 * i - 1] if data[2 * i - 1] < data[2 * i] else data[2 * i]

    def query(self, l, r):
        data = self.data
        N0 = self.N0
        ti = self.ti
        self.propagates(*self.gindex(l, r))
        L = N0 + l
        R = N0 + r
        vl = vr = ti
        while L < R:
            '''
            if R & 1:
                R -= 1
                vr = f(data[R - 1], vr)
            if L & 1:
                vl = f(vl, data[L - 1])
                L += 1
            '''
            if R & 1:
                R -= 1
                vr = data[R - 1] if data[R - 1] < vr else vr
            if L & 1:
                vl = vl if vl < data[L - 1] else data[L - 1]
                L += 1
            L >>= 1
            R >>= 1
        '''
        return f(vl, vr)
        '''
        return vl if vl < vr else vr


I = sys.stdin.read()[:-1].split('\n')
N, Q = map(int, I[0].split())

ti = 2**31 - 1  
ei = None



LST = LazySegmentTree([ti] * N, ti, ei)
ans = []
for r in I[1:]:
    t, *cmd = map(int, r.split())
    if t:
        s, t = cmd
        ans.append(str(LST.query(s, t + 1)))
    else:
        s, t, x = cmd
        LST.update(s, t + 1, x)

write("\n".join(ans))
write("\n")

Solution (Python):
import sys
input = sys.stdin.readline

N,Q=map(int,input().split())

seg_el=1<<(N.bit_length()) 
SEG=[(1<<31)-1]*(2*seg_el) 
LAZY=[None]*(2*seg_el) 


def indexes(L,R):
    INDLIST=[]

    R-=1
    
    L>>=1
    R>>=1

    while L!=R:
        if L>R:
            INDLIST.append(L)
            L>>=1
        else:
            INDLIST.append(R)
            R>>=1

    while L!=0:
        INDLIST.append(L)
        L>>=1

    return INDLIST
        

def updates(l,r,x): 
        
    L=l+seg_el
    R=r+seg_el

    L//=(L & (-L))
    R//=(R & (-R))

    UPIND=indexes(L,R)
    
    for ind in UPIND[::-1]:
        if LAZY[ind]!=None:
            LAZY[ind<<1]=LAZY[1+(ind<<1)]=SEG[ind<<1]=SEG[1+(ind<<1)]=LAZY[ind]
            LAZY[ind]=None
    
    while L!=R:
        if L > R:
            SEG[L]=x
            LAZY[L]=x
            L+=1
            L//=(L & (-L))

        else:
            R-=1
            SEG[R]=x
            LAZY[R]=x
            R//=(R & (-R))

    for ind in UPIND:
        SEG[ind]=min(SEG[ind<<1],SEG[1+(ind<<1)])  
        
def getvalues(l,r): 

    L=l+seg_el
    R=r+seg_el

    L//=(L & (-L))
    R//=(R & (-R))

    UPIND=indexes(L,R)
    
    for ind in UPIND[::-1]:
        if LAZY[ind]!=None:
            LAZY[ind<<1]=LAZY[1+(ind<<1)]=SEG[ind<<1]=SEG[1+(ind<<1)]=LAZY[ind]
            LAZY[ind]=None
            
    ANS=1<<31

    while L!=R:
        if L > R:
            ANS=min(ANS , SEG[L])
            L+=1
            L//=(L & (-L))

        else:
            R-=1
            ANS=min(ANS , SEG[R])
            R//=(R & (-R))

    return ANS

ANS=[]

for _ in range(Q):
    query=list(map(int,input().split()))
    if query[0]==0:
        updates(query[1],query[2]+1,query[3])

    else:
        ANS.append(getvalues(query[1],query[2]+1))


print("\n".join([str(ans) for ans in ANS]))

Solution (Python):


import sys

def input(): return sys.stdin.readline().strip()
def list2d(a, b, c): return [[c] * b for i in range(a)]
def list3d(a, b, c, d): return [[[d] * c for j in range(b)] for i in range(a)]
def list4d(a, b, c, d, e): return [[[[e] * d for j in range(c)] for j in range(b)] for i in range(a)]
def ceil(x, y=1): return int(-(-x // y))
def INT(): return int(input())
def MAP(): return map(int, input().split())
def LIST(N=None): return list(MAP()) if N is None else [INT() for i in range(N)]
def Yes(): print('Yes')
def No(): print('No')
def YES(): print('YES')
def NO(): print('NO')
sys.setrecursionlimit(10 ** 9)
INF = 2 ** 31 - 1
MOD = 10 ** 9 + 7

class SegTreeLazy:
    """ 遅延評価セグメント木 """

    def __init__(self, N, func, intv):
        self.intv = intv
        self.func = func
        LV = (N-1).bit_length()
        self.N0 = 2**LV
        self.data = [intv]*(2*self.N0)
        self.lazy = [None]*(2*self.N0)

    
    def gindex(self, l, r):
        L = l + self.N0; R = r + self.N0
        lm = (L // (L & -L)) >> 1
        rm = (R // (R & -R)) >> 1
        while L < R:
            if R <= rm:
                yield R
            if L <= lm:
                yield L
            L >>= 1; R >>= 1
        while L:
            yield L
            L >>= 1

    
    def propagates(self, *ids):
        
        for i in reversed(ids):
            v = self.lazy[i-1]
            if v is None:
                continue
            self.lazy[2*i-1] = self.data[2*i-1] = self.lazy[2*i] = self.data[2*i] = v
            self.lazy[i-1] = None

    def update(self, l, r, x):
        """ 区間[l,r)の値をxに更新 """

        *ids, = self.gindex(l, r)
        
        self.propagates(*ids)
        
        L = self.N0 + l; R = self.N0 + r
        while L < R:
            if R & 1:
                R -= 1
                self.lazy[R-1] = self.data[R-1] = x
            if L & 1:
                self.lazy[L-1] = self.data[L-1] = x
                L += 1
            L >>= 1; R >>= 1
        
        for i in ids:
            self.data[i-1] = self.func(self.data[2*i-1], self.data[2*i])

    def query(self, l, r):
        """ 区間[l,r)の最小値を取得 """

        
        self.propagates(*self.gindex(l, r))
        L = self.N0 + l; R = self.N0 + r

        
        s = self.intv
        while L < R:
            if R & 1:
                R -= 1
                s = self.func(s, self.data[R-1])
            if L & 1:
                s = self.func(s, self.data[L-1])
                L += 1
            L >>= 1; R >>= 1
        return s

N, Q = MAP()
stl = SegTreeLazy(N+1, min, INF)

ans = []
for i in range(Q):
    cmd, *arg = MAP()
    if cmd == 0:
        s, t, x = arg
        stl.update(s, t+1, x)
    else:
        s, t = arg
        ans.append(str(stl.query(s, t+1)))
print('\n'.join(ans))

Solution (Python):
import sys
input = sys.stdin.readline
INF = 2**31 - 1

class LazySegmentTree:
    def __init__(self, n):
        LV = (n-1).bit_length()
        self.N0 = 2 ** LV
        self.data = [INF] * (2*self.N0)
        self.lazy = [None] * (2*self.N0)
        
    def gindex(self, l, r):
        L = l + self.N0; R = r + self.N0
        lm = (L // (L & -L)) >> 1
        rm = (R // (R & -R)) >> 1
    
        while L < R:
            if R <= rm:
                yield R
            if L <= lm:
                yield L
            
            L >>= 1; R >>= 1
        
        while L:
            yield L
            L >>= 1

    def propagates(self, *ids):
        for i in reversed(ids):
            v = self.lazy[i-1]
            
            if v is None:
                continue
            
            self.lazy[2*i-1] = self.data[2*i-1] = self.lazy[2*i] = self.data[2*i] = v
            self.lazy[i-1] = None

    def update(self, l, r, x):
        *ids, = self.gindex(l, r)
        self.propagates(*ids)

        L = self.N0 + l; R = self.N0 + r
        
        while L < R:
            if R & 1:
                R -= 1
                self.lazy[R-1] = self.data[R-1] = x
            if L & 1:
                self.lazy[L-1] = self.data[L-1] = x
                L += 1
                
            L >>= 1; R >>= 1
            
        for i in ids:
            self.data[i-1] = min(self.data[2*i-1], self.data[2*i])

    def query(self, l, r):
        self.propagates(*self.gindex(l, r))
        L = self.N0 + l; R = self.N0 + r

        s = INF
        
        while L < R:
            if R & 1:
                R -= 1
                s = min(s, self.data[R-1])
            if L & 1:
                s = min(s, self.data[L-1])
                L += 1
                
            L >>= 1; R >>= 1
            
        return s

n, q = map(int, input().split())
lst = LazySegmentTree(n)

for _ in range(q):
    que = list(map(int, input().split()))
    
    if que[0] == 0:
        s, t, x = que[1], que[2], que[3]
        lst.update(s, t+1, x)
    elif que[0] == 1:
        s, t = que[1], que[2]
        print(lst.query(s, t+1))

Solution (Python):
class SegmentTree(object):
    INIT = 2 ** 31 - 1
    DIVIDED = -1

    def __init__(self, n: int) -> None:
        size = 1
        while size < n:
            size *= 2
        self.size = 2 * size - 1
        self.data = [-1] * self.size
        self.data[0] = self.INIT

    def set_range(self, l: int, h: int, v: int) -> None:
        def _set_range(r, i: int, j: int, vv: int) -> None:
            if (j < l or i > h):
                if vv != self.DIVIDED:
                    self.data[r] = vv
            elif (l <= i and j <= h):  
                self.data[r] = v
            else:
                if self.data[r] != self.DIVIDED:
                    if vv == self.DIVIDED:
                        vv = self.data[r]
                    self.data[r] = self.DIVIDED
                mid = i + (j - i) // 2
                _set_range(r * 2 + 1, i, mid, vv)
                _set_range(r * 2 + 2, mid + 1, j, vv)

        _set_range(0, 0, self.size // 2, self.DIVIDED)

    def min(self, i: int, j: int) -> int:
        def _min(r, l: int, h: int) -> int:
            if (j < l or i > h):
                return self.INIT
            elif self.data[r] != self.DIVIDED:
                return self.data[r]
            else:
                mid = l + (h - l) // 2
                return min(_min(r * 2 + 1, l, mid),
                           _min(r * 2 + 2, mid + 1, h))

        return _min(0, 0, self.size // 2)


if __name__ == "__main__":
    n, q = map(lambda x: int(x), input().split())
    segtree = SegmentTree(n)

    for _ in range(q):
        com, *v = map(lambda x: int(x), input().split())
        if (0 == com):
            segtree.set_range(v[0], v[1], v[2])
        else:
            print(segtree.min(v[0], v[1]))

Solution (Python):
from collections import defaultdict,deque
import sys,heapq,bisect,math,itertools,string,queue,copy,time
sys.setrecursionlimit(10**8)
INF = float('inf')
mod = 10**9+7
eps = 10**-7
print = sys.stdout.write
def inp(): return int(sys.stdin.readline())
def inpl(): return list(map(int, sys.stdin.readline().split()))
def inpl_str(): return list(sys.stdin.readline().split())

class SegmentTree:
    def __init__(self,N,d):
        self.N0 = 2**(N-1).bit_length()
        self.node = [d]*(self.N0*2)
        self.lazy = [None]*(self.N0*2)

    def gindex(self,l,r):
        L = l + self.N0
        R = r + self.N0
        lm = (L // (L & -L)) >> 1
        rm = (R // (R & -R)) >> 1
        while L < R:
            if R <= rm:
                yield R
            if L <= lm:
                yield L
            L >>= 1; R >>= 1
        while L:
            yield L
            L >>= 1

    def propagates(self,*ids):
        for i in reversed(ids):
            v = self.lazy[i-1]
            if v is None:
                continue
            self.lazy[2*i-1] = self.lazy[2*i] = v
            self.node[2*i-1] = self.node[2*i] = v
            self.lazy[i-1] = None

    def update(self,l,r,x): 
        *ids, = self.gindex(l, r)

        
        self.propagates(*ids)

        
        L = self.N0 + l
        R = self.N0 + r
        while L < R:
            if R & 1:
                R -= 1
                self.lazy[R-1] = self.node[R-1] = x
            if L & 1:
                self.lazy[L-1] = self.node[L-1] = x
                L += 1
            L >>= 1; R >>= 1

        
        for i in ids:
            self.node[i-1] = self.process(self.node[2*i-1], self.node[2*i])

    def query(self,l, r):
        
        self.propagates(*self.gindex(l, r))
        L = self.N0 + l
        R = self.N0 + r

        
        s = INF
        while L < R:
            if R & 1:
                R -= 1
                s = self.process(s, self.node[R-1])
            if L & 1:
                s = self.process(s, self.node[L-1])
                L += 1
            L >>= 1; R >>= 1
        return s

    def process(self,x,y): 
        return min(x,y)

N,Q = inpl()
ST = SegmentTree(N,2**31-1)
ans = []
for _ in range(Q):
    c,*arg = inpl()
    if c:
        s,t = arg
        ans.append(str(ST.query(s,t+1)))
    else:
        s,t,x = arg
        ST.update(s,t+1,x)

print('\n'.join(ans))
print('\n')

Solution (Python):
import sys
input = sys.stdin.readline
class LazySegTree:
    """
    遅延評価セグメント木
    デフォルト引数は RMQ and RUQ
    値の更新・取得は半開区間
    内部実装は 1-indexed
    参考: https://yukicoder.me/submissions/295288

    """
    def __init__(self,
                 a,
                 op=lambda a,b: a if a<b else b,
                 op_e=(1<<31)-1,
                 ap=lambda a,b,length: a if a!=-1 else b,
                 cp=lambda a,b: a if a!=-1 else b,
                 ap_identity=-1):
        """
        :param a: 初期状態
        :param op: 区間取得のための関数
        :param op_e: 単位元
        :param ap: 区間更新のための関数　第1引数は作用させる値　第2引数はもとの値
        :param cp: ap を結合するための関数
        :param ap_identity: 恒等変換
        """
        self.n = n = len(a)
        self.op, self.op_e, self.ap, self.cp, self.ap_identity = op, op_e, ap, cp, ap_identity
        self.val = val = [op_e] * n + a
        self.act = [ap_identity] * n
        self.length = length = [1] * (2*n)
        l = 2*n-2
        for i in range(n-1, 0, -1):
            r = l+1
            length[i] = length[l] + length[r]
            val[i] = op(val[l], val[r])
            l -= 2

    def get(self, l, r):
        self._push(l, r)
        res_l = res_r = self.op_e
        l += self.n
        r += self.n
        val, op = self.val, self.op
        while l < r:
            if l & 1:
                res_l = op(res_l, val[l])
            if r & 1:
                res_r = op(val[r-1], res_r)
            l = l+1 >> 1
            r >>= 1
        return op(res_l, res_r)

    def push(self):
        for i in range(1, self.n):
            self._push_one(i)

    def set(self, l, r, value):
        
        if l >= r:
            return
        n, ap, val, op, act, cp, length = self.n, self.ap, self.val, self.op, self.act, self.cp, self.length
        self._push(l, r)
        l = i = l + n
        r = j = r + n
        if i & 1: val[i] = ap(value, val[i], length[i])
        if j & 1: j-=1; val[j] = ap(value, val[j], length[j])
        i = i+1 >> 1
        j >>= 1
        while i < j:
            if i & 1:
                val[i] = ap(value, val[i], length[i])
                act[i] = cp(value, act[i])
            if j & 1:
                j -= 1
                val[j] = ap(value, val[j], length[j])
                act[j] = cp(value, act[j])
            i = i+1 >> 1
            j >>= 1
        l = l // (l & -l) >> 1
        while l>0:
            val[l] = op(val[2*l], val[2*l+1])
            l >>= 1
        r = r // (r & -r) >> 1
        while r>0:
            val[r] = op(val[2*r], val[2*r+1])
            r >>= 1

    def set_one(self, i, value):
        
        val, op = self.val, self.op
        self._push(i, i+1)
        i += self.n
        val[i] = value
        i >>= 1
        while i>0:
            val[i] = op(val[2*i], val[2*i+1])
            i >>= 1

    def _ap(self, value, i):
        
        self.val[i] = self.ap(value, self.val[i], self.length[i])
        if i < self.n:
            self.act[i] = self.cp(value, self.act[i])

    def _push_one(self, i):
        act = self.act
        self._ap(act[i], 2*i)
        self._ap(act[i], 2*i+1)
        act[i] = self.ap_identity

    def _push(self, l, r):
        n, act, ap_identity, ap, cp, val, length = self.n, self.act, self.ap_identity, self.ap, self.cp, self.val, self.length
        ln = l + n
        rnm1 = r + n - 1
        hl = ln.bit_length()-1
        hr = rnm1.bit_length()-1
        for hr in range(hr, 0, -1):
            al = ln >> hl
            ar = rnm1 >> hr
            if al < n:
                
                al_l = 2 * al
                al_r = al_l + 1
                act_al = act[al]
                val[al_l] = ap(act_al, val[al_l], length[al_l])
                if al_l < n:
                    act[al_l] = cp(act_al, act[al_l])
                val[al_r] = ap(act_al, val[al_r], length[al_r])
                if al_r < n:
                    act[al_r] = cp(act_al, act[al_r])
                act[al] = ap_identity
            if ar != al:
                
                ar_l = 2 * ar
                ar_r = ar_l + 1
                act_ar = act[ar]
                val[ar_l] = ap(act_ar, val[ar_l], length[ar_l])
                if ar_l < n:
                    act[ar_l] = cp(act_ar, act[ar_l])
                val[ar_r] = ap(act_ar, val[ar_r], length[ar_r])
                if ar_r < n:
                    act[ar_r] = cp(act_ar, act[ar_r])
                act[ar] = ap_identity
            hl -= 1


N, Q = map(int, input().split())
tree = LazySegTree([(1<<31)-1]*N)
ans = []
for i in range(Q):
    q, *A = map(int, input().split())
    if q==0:
        s, t, x = A
        tree.set(s, t+1, x)
    else:
        s, t = A
        ans.append(tree.get(s, t+1))
print("\n".join(map(str, ans)))

Solution (Python):
import sys
input=sys.stdin.readline

def gindex(l,r):
    L,R=l+N0,r+N0
    lm=L//(L&-L)>>1
    rm=R//(R&-R)>>1
    while L<R:
        if R<=rm:
            yield R
        if L<=lm:
            yield L
        L>>=1
        R>>=1
    while L:
        yield L
        L>>=1
def propagates(*ids):
    for i in reversed(ids):
        v=lazy[i-1]
        if v==None:
            continue
        lazy[2*i-1]=v
        lazy[2*i]=v
        data[2*i-1]=v
        data[2*i]=v
        lazy[i-1]=None
def update(l,r,x):
    L,R=N0+l,N0+r
    *ids,=gindex(l,r)
    propagates(*ids)
    while L<R:
        if R&1:
            R-=1
            lazy[R-1]=x
            data[R-1]=x
        if L&1:
            lazy[L-1]=x
            data[L-1]=x
            L+=1
        L>>=1
        R>>=1
    for i in ids:
        data[i-1]=min(data[2*i-1],data[2*i])
def query(l,r):
    propagates(*gindex(l,r))
    L,R=N0+l,N0+r
    s=INF
    while L<R:
        if R&1:
            R-=1
            s=min(s,data[R-1])
        if L&1:
            s=min(s,data[L-1])
            L+=1
        L>>=1
        R>>=1
    return s
n,q=map(int,input().split())

LV=n.bit_length()
N0=2**LV
INF=2**40
data=[2**31-1]*2*N0
lazy=[None]*2*N0
for i in range(q):
    l=list(map(int,input().split()))
    if l[0]==0:
        s,t,x=l[1:]
        update(s,t+1,x)
    else:
        s,t=l[1:]
        print(query(s,t+1))

Solution (Python):
import sys
class Lazysegtree:
    def __init__(self, A, intv, initialize = True):
        
        self.N = len(A)
        self.N0 = 2**(self.N-1).bit_length()
        self.intv = intv
        
        self.lazy = [None]*(2*self.N0)
        if initialize:
            self.data = [intv]*self.N0 + A + [intv]*(self.N0 - self.N)
            for i in range(self.N0-2, -1, -1):
                self.data[i] = min(self.data[2*i], self.data[2*i+1]) 
        else:
            self.data = [intv]*(2*self.N0)
  
    def _ascend(self, k):
        k = k >> 1
        c = k.bit_length()
        for j in range(c):
            idx = k >> j
            self.data[idx] = min(self.data[2*idx], self.data[2*idx+1])
              
    def _descend(self, k):
        k = k >> 1
        idx = 1
        c = k.bit_length()
        for j in range(1, c+1):
            idx = k >> (c - j)
            if self.lazy[idx] is None:
                continue
            self.data[2*idx] = self.data[2*idx+1] = self.lazy[2*idx] \
            = self.lazy[2*idx+1] = self.lazy[idx] 
            self.lazy[idx] = None
              
              
    def query(self, l, r):
        L = l+self.N0
        R = r+self.N0
        self._descend(L//(L & -L))
        self._descend(R//(R & -R) - 1)
          
        s = self.intv                                                                   
  
        while L < R:
            if R & 1:
                R -= 1
                s = min(s, self.data[R])
            if L & 1:
                s = min(s, self.data[L])
                L += 1
            L >>= 1
            R >>= 1
        return s
      
    def update(self, l, r, x):
        L = l+self.N0
        R = r+self.N0
  
        Li = L//(L & -L)
        Ri = R//(R & -R)
        self._descend(Li)
        self._descend(Ri-1)
          
        while L < R :
            if R & 1:
                R -= 1
                self.data[R] = x
                self.lazy[R] = x
            if L & 1:
                self.data[L] = x
                self.lazy[L] = x
                L += 1
            L >>= 1
            R >>= 1
          
        self._ascend(Li)
        self._ascend(Ri-1)
  
N, Q = map(int, input().split())
T = Lazysegtree([None]*N, 2**31-1, initialize = False) 
Ans = []
for _ in range(Q):
    t, *q = map(int, sys.stdin.readline().split())
    q[1] += 1
    if t:
        Ans.append(T.query(*q))
    else:
        T.update(*q)
print('\n'.join(map(str, Ans)))

Solution (Python):
import sys
input = sys.stdin.readline

n, q = map(int, input().split())
INF = 2**31-1

Len = (n-1).bit_length()
size = 2**Len
tree = [INF]*(2*size)
lazy = [None]*(2*size)

def gindex(l,r):
    L = (l+size)>>1;R=(r+size)>>1
    lc = 0 if l & 1 else (L&-L).bit_length()
    rc = 0 if r & 1 else (R&-R).bit_length()
    for i in range(Len):
        if rc <= i:
            yield R
        if L < R and lc <= i:
            yield L
        L >>= 1; R >>= 1
        
        

def propagates(ids):
    
    for i in reversed(ids):
        v = lazy[i]
        if v is None:
            continue
        lazy[2*i]=tree[2*i]=lazy[2*i+1]=tree[2*i+1]=v
        lazy[i]=None


def update(l,r,x):
    *ids, = gindex(l, r)
    propagates(ids)
    
    L = size+l
    R = size+r
    while L<R:
        if R&1:
            R -= 1
            lazy[R]=tree[R]=x
        if L&1:
            lazy[L]=tree[L]=x
            L+=1
        L>>=1;R>>=1
    
    for i in ids:
        if 2*i+1<size*2:
            tree[i]=min(tree[i*2],tree[i*2+1])
        
def query(l, r):
    *ids, = gindex(l, r)
    propagates(ids)
    L = size + l
    R = size + r
    s = INF
    while L<R:
        if R&1:
            R-=1
            s = min(s,tree[R])
        if L&1:
            s = min(s,tree[L])
            L+=1
        L>>=1;R>>=1
    return s

ans = []
for i in range(q):
    a, *b = map(int, input().split())
    if a:
        ans.append(query(b[0],b[1]+1))
    else:
        update(b[0],b[1]+1,b[2])
        
print('\n'.join(map(str,ans)))

Solution (Python):
import sys
readline = sys.stdin.readline
write = sys.stdout.write
 
N, Q = map(int, input().split())
INF = 2**31-1
 
LV = (N-1).bit_length()
N0 = 2**LV
data = [INF]*(2*N0)
lazy = [None]*(2*N0)
 
def gindex(l, r):
    L = (l + N0) >> 1; R = (r + N0) >> 1
    lc = 0 if l & 1 else (L & -L).bit_length()
    rc = 0 if r & 1 else (R & -R).bit_length()
    for i in range(LV):
        if rc <= i:
            yield R
        if L < R and lc <= i:
            yield L
        L >>= 1; R >>= 1
 
def propagates(*ids):
    for i in reversed(ids):
        v = lazy[i-1]
        if v is None:
            continue
        lazy[2*i-1] = data[2*i-1] = lazy[2*i] = data[2*i] = v
        lazy[i-1] = None
 
def update(l, r, x):
    *ids, = gindex(l, r)
    propagates(*ids)
 
    L = N0 + l; R = N0 + r
    while L < R:
        if R & 1:
            R -= 1
            lazy[R-1] = data[R-1] = x
        if L & 1:
            lazy[L-1] = data[L-1] = x
            L += 1
        L >>= 1; R >>= 1
    for i in ids:
        data[i-1] = min(data[2*i-1], data[2*i])
 
def query(l, r):
    propagates(*gindex(l, r))
    L = N0 + l; R = N0 + r
 
    s = INF
    while L < R:
        if R & 1:
            R -= 1
            s = min(s, data[R-1])
        if L & 1:
            s = min(s, data[L-1])
            L += 1
        L >>= 1; R >>= 1
    return s
 
 
answer = []
for q in range(Q):
    t, *cmd = map(int, readline().split())
    if t:
        s, t = cmd
        answer.append(str(query(s, t+1)))
    else:
        s, t, x = cmd
        update(s, t+1, x)
 
write("\n".join(answer))
write("\n")

Solution (Python):
import sys
readline = sys.stdin.readline
write = sys.stdout.write

N, Q = map(int, input().split())
INF = 2**31-1

LV = (N-1).bit_length()
N0 = 2**LV
data = [INF]*(2*N0)
lazy = [None]*(2*N0)

def gindex(l, r):
    L = (l + N0) >> 1; R = (r + N0) >> 1
    lc = 0 if l & 1 else (L & -L).bit_length()
    rc = 0 if r & 1 else (R & -R).bit_length()
    for i in range(LV):
        if rc <= i:
            yield R
        if L < R and lc <= i:
            yield L
        L >>= 1; R >>= 1

def propagates(*ids):
    for i in reversed(ids):
        v = lazy[i-1]
        if v is None:
            continue
        lazy[2*i-1] = data[2*i-1] = lazy[2*i] = data[2*i] = v
        lazy[i-1] = None

def update(l, r, x):
    *ids, = gindex(l, r)
    propagates(*ids)

    L = N0 + l; R = N0 + r
    while L < R:
        if R & 1:
            R -= 1
            lazy[R-1] = data[R-1] = x
        if L & 1:
            lazy[L-1] = data[L-1] = x
            L += 1
        L >>= 1; R >>= 1
    for i in ids:
        data[i-1] = min(data[2*i-1], data[2*i])

def query(l, r):
    propagates(*gindex(l, r))
    L = N0 + l; R = N0 + r

    s = INF
    while L < R:
        if R & 1:
            R -= 1
            s = min(s, data[R-1])
        if L & 1:
            s = min(s, data[L-1])
            L += 1
        L >>= 1; R >>= 1
    return s


ans = []
for q in range(Q):
    t, *cmd = map(int, readline().split())
    if t:
        s, t = cmd
        ans.append(str(query(s, t+1)))
    else:
        s, t, x = cmd
        update(s, t+1, x)

write("\n".join(ans))
write("\n")

Solution (Python):





class SegmentTree:
    INITIAL_VALUE = 2**31 - 1
    DIVIDED = -1

    def __init__(self, n):
        size = 1
        while size < n:
            size *= 2
        self.size = 2*size - 1
        self.data = [-1] * self.size
        self.data[0] = self.INITIAL_VALUE

    def set_range(self, lo, hi, v):
        def _set_range(r, i, j, vv):
            if j < lo or i > hi:
                if vv != self.DIVIDED:
                    self.data[r] = vv
            elif lo <= i and j <= hi:
                self.data[r] = v
            else:
                if self.data[r] != self.DIVIDED:
                    if vv == self.DIVIDED:
                        vv = self.data[r]
                    self.data[r] = self.DIVIDED
                mid = i + (j - i)//2
                _set_range(r*2 + 1, i, mid, vv)
                _set_range(r*2 + 2, mid+1, j, vv)

        _set_range(0, 0, self.size//2, self.DIVIDED)

    def min(self, i, j):
        def _min(r, lo, hi):
            if j < lo or i > hi:
                return self.INITIAL_VALUE
            elif self.data[r] != self.DIVIDED:
                return self.data[r]
            else:
                mid = lo + (hi - lo)//2
                return min(_min(r*2 + 1, lo, mid),
                           _min(r*2 + 2, mid+1, hi))

        return _min(0, 0, self.size//2)


def run():
    n, q = [int(i) for i in input().split()]

    tree = SegmentTree(n)

    for _ in range(q):
        com, *args = input().split()
        if com == '0':
            s, t, x = [int(i) for i in args]
            tree.set_range(s, t, x)
        elif com == '1':
            s, t = [int(i) for i in args]
            print(tree.min(s, t))


if __name__ == '__main__':
    run()