Buggy python submission (verdict: Runtime Error):
import sys
import os
import numpy as np

def solve(inp):
    MOD = 998244353

    def bit_length(x):
        ret = 0
        while x:
            x >>= 1
            ret += 1
        return ret

    e = 0
    id_x = -1

    n = inp[0]
    q = inp[1]
    X = inp[2::3]
    Y = inp[3::3]
    REP = inp[4::3]
    log = bit_length(n - 1)
    size = 1 << log
    d = [e] * (2 * size)
    lz = [id_x] * size


    def op(a, b):
        a1, a2 = a >> 32, a % (1 << 32)
        b1, b2 = b >> 32, b % (1 << 32)
        c1 = (a1 + b1) % MOD
        c2 = (a2 + b2) % MOD
        return (c1 << 32) + c2


    def mapping(x, a):
        if x == -1:
            return a
        a1, a2 = a >> 32, a % (1 << 32)
        c1 = (x * a2) % MOD
        c2 = a2
        return (c1 << 32) + c2


    def composition(x, y):
        if x == -1:
            return y
        return x


    # ----- seg tree設定 ここまで ----- #


    def update(k):
        d[k] = op(d[2 * k], d[2 * k + 1])


    def all_apply(k, f):
        d[k] = mapping(f, d[k])
        if k < size:
            lz[k] = composition(f, lz[k])


    def push(k):
        all_apply(2 * k, lz[k])
        all_apply(2 * k + 1, lz[k])
        lz[k] = id_x


    def build(arr):
        assert len(arr) == n
        for j in range(n):
            d[size + j] = arr[j]
        for j in range(size - 1, 0, -1):
            update(j)


    def set(p, x):
        assert 0 <= p < n
        p += size
        for i in range(1, log + 1)[::-1]:
            push(p >> i)
        d[p] = x
        for i in range(1, log + 1):
            update(p >> i)


    def get(p):
        assert 0 <= p < n
        p += size
        for i in range(1, log + 1):
            push(p >> i)
        return d[p]


    def prod(l, r):
        assert 0 <= l <= r <= n
        if l == r:
            return e
        l += size
        r += size
        for i in range(1, log + 1)[::-1]:
            if ((l >> i) << i) != l:
                push(l >> i)
            if ((r >> i) << i) != r:
                push(r >> i)
        sml = smr = e
        while l < r:
            if l & 1:
                sml = op(sml, d[l])
                l += 1
            if r & 1:
                r -= 1
                smr = op(d[r], smr)
            l >>= 1
            r >>= 1
        return op(sml, smr)


    def all_prod():
        return d[1]


    def apply(p, f):
        assert 0 <= p < n
        p += size
        for i in range(1, log + 1)[::-1]:
            push(p >> i)
        d[p] = mapping(f, d[p])
        for i in range(1, log + 1):
            update(p >> i)


    def range_apply(l, r, f):
        assert 0 <= l <= r <= n
        if l == r:
            return
        l += size
        r += size
        for i in range(log, 0, -1):
            if ((l >> i) << i) != l:
                push(l >> i)
            if ((r >> i) << i) != r:
                push((r - 1) >> i)
        l2 = l
        r2 = r
        while l < r:
            if l & 1:
                all_apply(l, f)
                l += 1
            if r & 1:
                r -= 1
                all_apply(r, f)
            l >>= 1
            r >>= 1
        l = l2
        r = r2
        for i in range(1, log + 1):
            if ((l >> i) << i) != l:
                update(l >> i)
            if ((r >> i) << i) != r:
                update((r - 1) >> i)


    def max_right(l, g):
        assert 0 <= l <= n
        # assert g(e)
        if l == n:
            return n
        l += size
        for i in range(1, log + 1)[::-1]:
            push(l >> i)
        sm = e
        while True:
            while l % 2 == 0:
                l >>= 1
            if not g(op(sm, d[l])):
                while l < size:
                    push(l)
                    l = 2 * l
                    if g(op(sm, d[l])):
                        sm = op(sm, d[l])
                        l += 1
                return l - size
            sm = op(sm, d[l])
            l += 1
            if (l & -l) == l:
                return n


    def min_left(r, g):
        assert 0 <= r <= n
        assert g(e)
        if r == 0:
            return 0
        r += size
        for i in range(1, log + 1)[::-1]:
            push((r - 1) >> i)
        sm = e
        while True:
            r -= 1
            while r > 1 and r % 2:
                r >>= 1
            if not g(op(d[r], sm)):
                while r < size:
                    push(r)
                    r = 2 * r + 1
                    if g(op(d[r], sm)):
                        sm = op(d[r], sm)
                        r -= 1
                return r + 1 - size
            sm = op(d[r], sm)
            if (r & -r) == r:
                return 0

    A = np.zeros(n, dtype=np.int64)
    tmp = 1
    for i in range(n - 1, -1, -1):
        A[i] = (tmp << 32) + tmp
        tmp *= 10
        tmp %= MOD

    build(A)

    ans = np.zeros(q, dtype=np.int64)
    for i in range(q):
        range_apply(X[i] - 1, Y[i], REP[i])
        ans[i] = all_prod() >> 32

    return '\n'.join(map(str, ans))


if sys.argv[-1] == 'ONLINE_JUDGE':
    from numba.pycc import CC

    cc = CC('my_module')
    cc.export('solve', '(i8[:],)')(solve)
    cc.compile()
    exit()

if os.name == 'posix':
    # noinspection PyUnresolvedReferences
    from my_module import solve
else:
    from numba import njit

    solve = njit('(i8[:],)', cache=True)(solve)
    print('compiled', file=sys.stderr)

inp = np.fromstring(sys.stdin.read(), dtype=np.int64, sep=' ')
ans = solve(inp)
print(ans)


Fixed submission:
import sys

input = sys.stdin.readline

MOD = 998244353

# ----- seg tree設定 ----- #

e = 0
id_x = -1


def op(a, b):
    a1, a2 = a >> 32, a % (1 << 32)
    b1, b2 = b >> 32, b % (1 << 32)
    c1 = (a1 + b1) % MOD
    c2 = (a2 + b2) % MOD
    return (c1 << 32) + c2


def mapping(x, a):
    if x == -1:
        return a
    a1, a2 = a >> 32, a % (1 << 32)
    c1 = (x * a2) % MOD
    c2 = a2
    return (c1 << 32) + c2


def composition(x, y):
    if x == -1:
        return y
    return x


# ----- seg tree設定 ここまで ----- #


def update(k):
    d[k] = op(d[2 * k], d[2 * k + 1])


def all_apply(k, f):
    d[k] = mapping(f, d[k])
    if k < size:
        lz[k] = composition(f, lz[k])


def push(k):
    all_apply(2 * k, lz[k])
    all_apply(2 * k + 1, lz[k])
    lz[k] = id_x


def build(arr):
    assert len(arr) == n
    for j in range(n):
        d[size + j] = arr[j]
    for j in range(1, size)[::-1]:
        update(j)


def set(p, x):
    assert 0 <= p < n
    p += size
    for i in range(1, log + 1)[::-1]:
        push(p >> i)
    d[p] = x
    for i in range(1, log + 1):
        update(p >> i)


def get(p):
    assert 0 <= p < n
    p += size
    for i in range(1, log + 1):
        push(p >> i)
    return d[p]


def prod(l, r):
    assert 0 <= l <= r <= n
    if l == r:
        return e
    l += size
    r += size
    for i in range(1, log + 1)[::-1]:
        if ((l >> i) << i) != l:
            push(l >> i)
        if ((r >> i) << i) != r:
            push(r >> i)
    sml = smr = e
    while l < r:
        if l & 1:
            sml = op(sml, d[l])
            l += 1
        if r & 1:
            r -= 1
            smr = op(d[r], smr)
        l >>= 1
        r >>= 1
    return op(sml, smr)


def all_prod():
    return d[1]


def apply(p, f):
    assert 0 <= p < n
    p += size
    for i in range(1, log + 1)[::-1]:
        push(p >> i)
    d[p] = mapping(f, d[p])
    for i in range(1, log + 1):
        update(p >> i)


def range_apply(l, r, f):
    assert 0 <= l <= r <= n
    if l == r:
        return
    l += size
    r += size
    for i in range(1, log + 1)[::-1]:
        if ((l >> i) << i) != l:
            push(l >> i)
        if ((r >> i) << i) != r:
            push((r - 1) >> i)
    l2 = l
    r2 = r
    while l < r:
        if l & 1:
            all_apply(l, f)
            l += 1
        if r & 1:
            r -= 1
            all_apply(r, f)
        l >>= 1
        r >>= 1
    l = l2
    r = r2
    for i in range(1, log + 1):
        if ((l >> i) << i) != l:
            update(l >> i)
        if ((r >> i) << i) != r:
            update((r - 1) >> i)


def max_right(l, g):
    assert 0 <= l <= n
    # assert g(e)
    if l == n:
        return n
    l += size
    for i in range(1, log + 1)[::-1]:
        push(l >> i)
    sm = e
    while True:
        while l % 2 == 0:
            l >>= 1
        if not g(op(sm, d[l])):
            while l < size:
                push(l)
                l = 2 * l
                if g(op(sm, d[l])):
                    sm = op(sm, d[l])
                    l += 1
            return l - size
        sm = op(sm, d[l])
        l += 1
        if (l & -l) == l:
            return n


def min_left(r, g):
    assert 0 <= r <= n
    assert g(e)
    if r == 0:
        return 0
    r += size
    for i in range(1, log + 1)[::-1]:
        push((r - 1) >> i)
    sm = e
    while True:
        r -= 1
        while r > 1 and r % 2:
            r >>= 1
        if not g(op(d[r], sm)):
            while r < size:
                push(r)
                r = 2 * r + 1
                if g(op(d[r], sm)):
                    sm = op(d[r], sm)
                    r -= 1
            return r + 1 - size
        sm = op(d[r], sm)
        if (r & -r) == r:
            return 0


n, q = map(int, input().split())
log = (n - 1).bit_length()
size = 1 << log
d = [e] * (2 * size)
lz = [id_x] * size

A = [0] * n
tmp = 1
for i in range(n - 1, -1, -1):
    A[i] = (tmp << 32) + tmp
    tmp *= 10
    tmp %= MOD

build(A)

ans = [0] * q
for i in range(q):
    x, y, rep = map(int, input().split())
    range_apply(x - 1, y, rep)
    ans[i] = all_prod() >> 32

print('\n'.join(map(str, ans)))

Buggy python submission (verdict: Time Limit Exceeded):
from operator import add

MOD = 998244353

class SegTreeLazy:
    """ 遅延評価セグメント木(区間更新、区間合計取得) """

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

    # 伝搬される区間のインデックス(1-indexed)を全て列挙するgenerator
    def gindex(self, l, r):
        L = (l + self.N0) >> 1; R = (r + self.N0) >> 1
        lc = 0 if l & 1 else (L & -L).bit_length()
        rc = 0 if r & 1 else (R & -R).bit_length()
        v = 2
        for i in range(self.LV):
            if rc <= i:
                yield R
            if L < R and lc <= i:
                yield L
            L >>= 1; R >>= 1; v <<= 1

    # 遅延評価の伝搬処理
    def propagates(self, *ids):
        # 1-indexedで単調増加のインデックスリスト
        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 >> 1
            self.lazy[i-1] = None

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

        *ids, = self.gindex(l, r)
        # 1. トップダウンにlazyの値を伝搬
        self.propagates(*ids)
        # 2. 区間[l,r)のdata, lazyの値を更新
        L = self.N0 + l; R = self.N0 + r
        v = x
        while L < R:
            if R & 1:
                R -= 1
                self.lazy[R-1] = self.data[R-1] = v
            if L & 1:
                self.lazy[L-1] = self.data[L-1] = v
                L += 1
            L >>= 1; R >>= 1; v <<= 1
        # 3. 伝搬させた区間について、ボトムアップにdataの値を伝搬する
        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)の和を取得 """

        # 1. トップダウンにlazyの値を伝搬
        self.propagates(*self.gindex(l, r))
        L = self.N0 + l; R = self.N0 + r

        # 2. 区間[l, 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(int, input().split())
stl = SegTreeLazy(n + 1, add, 0)

ans = []
for i in range(q):
    l, r, rep = map(int, input().split())
    stl.update(l - 1, r, rep)
    tmp = [stl.query(x, x + 1) for x in range(n)]
    res = "".join(map(str, tmp)).replace("0", "1")
    print(int(res) % MOD)


Fixed submission:
import sys

input = sys.stdin.readline

MOD = 998244353

# ----- seg tree設定 ----- #

e = 0
id_x = -1


def op(a, b):
    a1, a2 = a >> 32, a % (1 << 32)
    b1, b2 = b >> 32, b % (1 << 32)
    c1 = (a1 + b1) % MOD
    c2 = (a2 + b2) % MOD
    return (c1 << 32) + c2


def mapping(x, a):
    if x == -1:
        return a
    a1, a2 = a >> 32, a % (1 << 32)
    c1 = (x * a2) % MOD
    c2 = a2
    return (c1 << 32) + c2


def composition(x, y):
    if x == -1:
        return y
    return x


# ----- seg tree設定 ここまで ----- #


def update(k):
    d[k] = op(d[2 * k], d[2 * k + 1])


def all_apply(k, f):
    d[k] = mapping(f, d[k])
    if k < size:
        lz[k] = composition(f, lz[k])


def push(k):
    all_apply(2 * k, lz[k])
    all_apply(2 * k + 1, lz[k])
    lz[k] = id_x


def build(arr):
    assert len(arr) == n
    for j in range(n):
        d[size + j] = arr[j]
    for j in range(1, size)[::-1]:
        update(j)


def set(p, x):
    assert 0 <= p < n
    p += size
    for i in range(1, log + 1)[::-1]:
        push(p >> i)
    d[p] = x
    for i in range(1, log + 1):
        update(p >> i)


def get(p):
    assert 0 <= p < n
    p += size
    for i in range(1, log + 1):
        push(p >> i)
    return d[p]


def prod(l, r):
    assert 0 <= l <= r <= n
    if l == r:
        return e
    l += size
    r += size
    for i in range(1, log + 1)[::-1]:
        if ((l >> i) << i) != l:
            push(l >> i)
        if ((r >> i) << i) != r:
            push(r >> i)
    sml = smr = e
    while l < r:
        if l & 1:
            sml = op(sml, d[l])
            l += 1
        if r & 1:
            r -= 1
            smr = op(d[r], smr)
        l >>= 1
        r >>= 1
    return op(sml, smr)


def all_prod():
    return d[1]


def apply(p, f):
    assert 0 <= p < n
    p += size
    for i in range(1, log + 1)[::-1]:
        push(p >> i)
    d[p] = mapping(f, d[p])
    for i in range(1, log + 1):
        update(p >> i)


def range_apply(l, r, f):
    assert 0 <= l <= r <= n
    if l == r:
        return
    l += size
    r += size
    for i in range(1, log + 1)[::-1]:
        if ((l >> i) << i) != l:
            push(l >> i)
        if ((r >> i) << i) != r:
            push((r - 1) >> i)
    l2 = l
    r2 = r
    while l < r:
        if l & 1:
            all_apply(l, f)
            l += 1
        if r & 1:
            r -= 1
            all_apply(r, f)
        l >>= 1
        r >>= 1
    l = l2
    r = r2
    for i in range(1, log + 1):
        if ((l >> i) << i) != l:
            update(l >> i)
        if ((r >> i) << i) != r:
            update((r - 1) >> i)


def max_right(l, g):
    assert 0 <= l <= n
    # assert g(e)
    if l == n:
        return n
    l += size
    for i in range(1, log + 1)[::-1]:
        push(l >> i)
    sm = e
    while True:
        while l % 2 == 0:
            l >>= 1
        if not g(op(sm, d[l])):
            while l < size:
                push(l)
                l = 2 * l
                if g(op(sm, d[l])):
                    sm = op(sm, d[l])
                    l += 1
            return l - size
        sm = op(sm, d[l])
        l += 1
        if (l & -l) == l:
            return n


def min_left(r, g):
    assert 0 <= r <= n
    assert g(e)
    if r == 0:
        return 0
    r += size
    for i in range(1, log + 1)[::-1]:
        push((r - 1) >> i)
    sm = e
    while True:
        r -= 1
        while r > 1 and r % 2:
            r >>= 1
        if not g(op(d[r], sm)):
            while r < size:
                push(r)
                r = 2 * r + 1
                if g(op(d[r], sm)):
                    sm = op(d[r], sm)
                    r -= 1
            return r + 1 - size
        sm = op(d[r], sm)
        if (r & -r) == r:
            return 0


n, q = map(int, input().split())
log = (n - 1).bit_length()
size = 1 << log
d = [e] * (2 * size)
lz = [id_x] * size

A = [0] * n
tmp = 1
for i in range(n - 1, -1, -1):
    A[i] = (tmp << 32) + tmp
    tmp *= 10
    tmp %= MOD

build(A)

ans = [0] * q
for i in range(q):
    x, y, rep = map(int, input().split())
    range_apply(x - 1, y, rep)
    ans[i] = all_prod() >> 32

print('\n'.join(map(str, ans)))

Buggy python submission (verdict: Time Limit Exceeded):
import sys
input = lambda: sys.stdin.readline()


def solve():
    def init(init_arr):
        global num, segfunc, ide_ele, seg
        segfunc = lambda x, y: y
        ide_ele = 0
        num = 2 ** (n - 1).bit_length()
        seg = [ide_ele] * 2 * num
        for i in range(n):
            seg[i + num - 1] = init_arr[i]
        for i in range(num - 2, -1, -1):
            seg[i] = segfunc(seg[2 * i + 1], seg[2 * i + 2])

    def update(k, x):
        k += num - 1
        seg[k] = x
        while k:
            k = (k - 1) // 2
            seg[k] = segfunc(seg[k * 2 + 1], seg[k * 2 + 2])

    def query(p, q):
        if q <= p:
            return ide_ele
        p += num - 1
        q += num - 2
        res = ide_ele
        while q - p > 1:
            if p & 1 == 0:
                res = segfunc(res, seg[p])
            if q & 1 == 1:
                res = segfunc(res, seg[q])
                q -= 1
            p = p // 2
            q = (q - 1) // 2
        if p == q:
            res = segfunc(res, seg[p])
        else:
            res = segfunc(segfunc(res, seg[p]), seg[q])
        return res

    n, q = map(int, input().split())
    a = [1] * n

    init(a)

    for _ in range(q):
        l, r, rep = map(int, input().split())
        for i in range(l - 1, r):
            update(i, rep)
        ans = []
        for i in range(n):
            ans.append(query(i, i + 1))
        print(int("".join(map(str, ans))) % 998244353)
solve()


Fixed submission:
import sys

input = sys.stdin.readline

MOD = 998244353

# ----- seg tree設定 ----- #

e = 0
id_x = -1


def op(a, b):
    a1, a2 = a >> 32, a % (1 << 32)
    b1, b2 = b >> 32, b % (1 << 32)
    c1 = (a1 + b1) % MOD
    c2 = (a2 + b2) % MOD
    return (c1 << 32) + c2


def mapping(x, a):
    if x == -1:
        return a
    a1, a2 = a >> 32, a % (1 << 32)
    c1 = (x * a2) % MOD
    c2 = a2
    return (c1 << 32) + c2


def composition(x, y):
    if x == -1:
        return y
    return x


# ----- seg tree設定 ここまで ----- #


def update(k):
    d[k] = op(d[2 * k], d[2 * k + 1])


def all_apply(k, f):
    d[k] = mapping(f, d[k])
    if k < size:
        lz[k] = composition(f, lz[k])


def push(k):
    all_apply(2 * k, lz[k])
    all_apply(2 * k + 1, lz[k])
    lz[k] = id_x


def build(arr):
    assert len(arr) == n
    for j in range(n):
        d[size + j] = arr[j]
    for j in range(1, size)[::-1]:
        update(j)


def set(p, x):
    assert 0 <= p < n
    p += size
    for i in range(1, log + 1)[::-1]:
        push(p >> i)
    d[p] = x
    for i in range(1, log + 1):
        update(p >> i)


def get(p):
    assert 0 <= p < n
    p += size
    for i in range(1, log + 1):
        push(p >> i)
    return d[p]


def prod(l, r):
    assert 0 <= l <= r <= n
    if l == r:
        return e
    l += size
    r += size
    for i in range(1, log + 1)[::-1]:
        if ((l >> i) << i) != l:
            push(l >> i)
        if ((r >> i) << i) != r:
            push(r >> i)
    sml = smr = e
    while l < r:
        if l & 1:
            sml = op(sml, d[l])
            l += 1
        if r & 1:
            r -= 1
            smr = op(d[r], smr)
        l >>= 1
        r >>= 1
    return op(sml, smr)


def all_prod():
    return d[1]


def apply(p, f):
    assert 0 <= p < n
    p += size
    for i in range(1, log + 1)[::-1]:
        push(p >> i)
    d[p] = mapping(f, d[p])
    for i in range(1, log + 1):
        update(p >> i)


def range_apply(l, r, f):
    assert 0 <= l <= r <= n
    if l == r:
        return
    l += size
    r += size
    for i in range(1, log + 1)[::-1]:
        if ((l >> i) << i) != l:
            push(l >> i)
        if ((r >> i) << i) != r:
            push((r - 1) >> i)
    l2 = l
    r2 = r
    while l < r:
        if l & 1:
            all_apply(l, f)
            l += 1
        if r & 1:
            r -= 1
            all_apply(r, f)
        l >>= 1
        r >>= 1
    l = l2
    r = r2
    for i in range(1, log + 1):
        if ((l >> i) << i) != l:
            update(l >> i)
        if ((r >> i) << i) != r:
            update((r - 1) >> i)


def max_right(l, g):
    assert 0 <= l <= n
    # assert g(e)
    if l == n:
        return n
    l += size
    for i in range(1, log + 1)[::-1]:
        push(l >> i)
    sm = e
    while True:
        while l % 2 == 0:
            l >>= 1
        if not g(op(sm, d[l])):
            while l < size:
                push(l)
                l = 2 * l
                if g(op(sm, d[l])):
                    sm = op(sm, d[l])
                    l += 1
            return l - size
        sm = op(sm, d[l])
        l += 1
        if (l & -l) == l:
            return n


def min_left(r, g):
    assert 0 <= r <= n
    assert g(e)
    if r == 0:
        return 0
    r += size
    for i in range(1, log + 1)[::-1]:
        push((r - 1) >> i)
    sm = e
    while True:
        r -= 1
        while r > 1 and r % 2:
            r >>= 1
        if not g(op(d[r], sm)):
            while r < size:
                push(r)
                r = 2 * r + 1
                if g(op(d[r], sm)):
                    sm = op(d[r], sm)
                    r -= 1
            return r + 1 - size
        sm = op(d[r], sm)
        if (r & -r) == r:
            return 0


n, q = map(int, input().split())
log = (n - 1).bit_length()
size = 1 << log
d = [e] * (2 * size)
lz = [id_x] * size

A = [0] * n
tmp = 1
for i in range(n - 1, -1, -1):
    A[i] = (tmp << 32) + tmp
    tmp *= 10
    tmp %= MOD

build(A)

ans = [0] * q
for i in range(q):
    x, y, rep = map(int, input().split())
    range_apply(x - 1, y, rep)
    ans[i] = all_prod() >> 32

print('\n'.join(map(str, ans)))

Buggy python submission (verdict: Time Limit Exceeded):
import sys
input = lambda: sys.stdin.readline()


def solve():
    def init(init_arr):
        global num, segfunc, ide_ele, seg
        segfunc = lambda x, y: y
        ide_ele = 0
        num = 2 ** (n - 1).bit_length()
        seg = [ide_ele] * 2 * num
        for i in range(n):
            seg[i + num - 1] = init_arr[i]
        for i in range(num - 2, -1, -1):
            seg[i] = segfunc(seg[2 * i + 1], seg[2 * i + 2])

    def update(k, x):
        k += num - 1
        seg[k] = x
        while k:
            k = (k - 1) // 2
            seg[k] = segfunc(seg[k * 2 + 1], seg[k * 2 + 2])

    def query(p, q):
        if q <= p:
            return ide_ele
        p += num - 1
        q += num - 2
        res = ide_ele
        while q - p > 1:
            if p & 1 == 0:
                res = segfunc(res, seg[p])
            if q & 1 == 1:
                res = segfunc(res, seg[q])
                q -= 1
            p = p // 2
            q = (q - 1) // 2
        if p == q:
            res = segfunc(res, seg[p])
        else:
            res = segfunc(segfunc(res, seg[p]), seg[q])
        return res

    n, q = map(int, input().split())
    a = [1] * n

    init(a)

    for _ in range(q):
        l, r, rep = map(int, input().split())
        for i in range(l - 1, r):
            update(i, rep)
        ans = ""
        for i in range(n):
            tmp = str(query(i, i + 1))
            ans = ans + tmp
        print(int(ans) % 998244353)
solve()


Fixed submission:
import sys

input = sys.stdin.readline

MOD = 998244353

# ----- seg tree設定 ----- #

e = 0
id_x = -1


def op(a, b):
    a1, a2 = a >> 32, a % (1 << 32)
    b1, b2 = b >> 32, b % (1 << 32)
    c1 = (a1 + b1) % MOD
    c2 = (a2 + b2) % MOD
    return (c1 << 32) + c2


def mapping(x, a):
    if x == -1:
        return a
    a1, a2 = a >> 32, a % (1 << 32)
    c1 = (x * a2) % MOD
    c2 = a2
    return (c1 << 32) + c2


def composition(x, y):
    if x == -1:
        return y
    return x


# ----- seg tree設定 ここまで ----- #


def update(k):
    d[k] = op(d[2 * k], d[2 * k + 1])


def all_apply(k, f):
    d[k] = mapping(f, d[k])
    if k < size:
        lz[k] = composition(f, lz[k])


def push(k):
    all_apply(2 * k, lz[k])
    all_apply(2 * k + 1, lz[k])
    lz[k] = id_x


def build(arr):
    assert len(arr) == n
    for j in range(n):
        d[size + j] = arr[j]
    for j in range(1, size)[::-1]:
        update(j)


def set(p, x):
    assert 0 <= p < n
    p += size
    for i in range(1, log + 1)[::-1]:
        push(p >> i)
    d[p] = x
    for i in range(1, log + 1):
        update(p >> i)


def get(p):
    assert 0 <= p < n
    p += size
    for i in range(1, log + 1):
        push(p >> i)
    return d[p]


def prod(l, r):
    assert 0 <= l <= r <= n
    if l == r:
        return e
    l += size
    r += size
    for i in range(1, log + 1)[::-1]:
        if ((l >> i) << i) != l:
            push(l >> i)
        if ((r >> i) << i) != r:
            push(r >> i)
    sml = smr = e
    while l < r:
        if l & 1:
            sml = op(sml, d[l])
            l += 1
        if r & 1:
            r -= 1
            smr = op(d[r], smr)
        l >>= 1
        r >>= 1
    return op(sml, smr)


def all_prod():
    return d[1]


def apply(p, f):
    assert 0 <= p < n
    p += size
    for i in range(1, log + 1)[::-1]:
        push(p >> i)
    d[p] = mapping(f, d[p])
    for i in range(1, log + 1):
        update(p >> i)


def range_apply(l, r, f):
    assert 0 <= l <= r <= n
    if l == r:
        return
    l += size
    r += size
    for i in range(1, log + 1)[::-1]:
        if ((l >> i) << i) != l:
            push(l >> i)
        if ((r >> i) << i) != r:
            push((r - 1) >> i)
    l2 = l
    r2 = r
    while l < r:
        if l & 1:
            all_apply(l, f)
            l += 1
        if r & 1:
            r -= 1
            all_apply(r, f)
        l >>= 1
        r >>= 1
    l = l2
    r = r2
    for i in range(1, log + 1):
        if ((l >> i) << i) != l:
            update(l >> i)
        if ((r >> i) << i) != r:
            update((r - 1) >> i)


def max_right(l, g):
    assert 0 <= l <= n
    # assert g(e)
    if l == n:
        return n
    l += size
    for i in range(1, log + 1)[::-1]:
        push(l >> i)
    sm = e
    while True:
        while l % 2 == 0:
            l >>= 1
        if not g(op(sm, d[l])):
            while l < size:
                push(l)
                l = 2 * l
                if g(op(sm, d[l])):
                    sm = op(sm, d[l])
                    l += 1
            return l - size
        sm = op(sm, d[l])
        l += 1
        if (l & -l) == l:
            return n


def min_left(r, g):
    assert 0 <= r <= n
    assert g(e)
    if r == 0:
        return 0
    r += size
    for i in range(1, log + 1)[::-1]:
        push((r - 1) >> i)
    sm = e
    while True:
        r -= 1
        while r > 1 and r % 2:
            r >>= 1
        if not g(op(d[r], sm)):
            while r < size:
                push(r)
                r = 2 * r + 1
                if g(op(d[r], sm)):
                    sm = op(d[r], sm)
                    r -= 1
            return r + 1 - size
        sm = op(d[r], sm)
        if (r & -r) == r:
            return 0


n, q = map(int, input().split())
log = (n - 1).bit_length()
size = 1 << log
d = [e] * (2 * size)
lz = [id_x] * size

A = [0] * n
tmp = 1
for i in range(n - 1, -1, -1):
    A[i] = (tmp << 32) + tmp
    tmp *= 10
    tmp %= MOD

build(A)

ans = [0] * q
for i in range(q):
    x, y, rep = map(int, input().split())
    range_apply(x - 1, y, rep)
    ans[i] = all_prod() >> 32

print('\n'.join(map(str, ans)))