module mint_mod
    use, intrinsic :: iso_fortran_env
    implicit none
    integer(int64) :: md = 998244353
    type,public:: mint
        integer(int64), private :: val = 0_8
    contains
        procedure:: to_int => mint_to_int64
    end type

    interface mint
        module procedure:: mi_init
    end interface
    interface operator( + )
        module procedure :: mi_add
    end interface
    interface operator( - )
        module procedure :: mi_sub
    end interface
    interface operator( * )
        module procedure :: mi_mul
    end interface
    interface operator( / )
        module procedure :: mi_div
    end interface
    interface operator( ** )
        module procedure :: mi_pow
    end interface
    interface assignment( = )
        module procedure:: mi_asgn
    end interface
    interface dot_product
        module procedure :: dot_prod
    end interface dot_product
    interface matmul
        module procedure :: matmul1, matmul2, matmul3
    end interface matmul
contains
    pure elemental function mi_init(num) result(ret)
        class(*),intent(in):: num
        type(mint):: ret
        ret = to_modint(num)
    end function



    pure elemental function to_int64(num) result(ret)
        class(*), intent(in) :: num
        integer(int64):: ret

        select type (num)
            type is (mint)
                ret = num%val
            type is (integer(int64))
                ret = num
            type is (integer(int32))
                ret = int(num, int64)
            type is (integer(int16))
                ret = int(num, int64)
            type is (integer(int8))
                ret = int(num, int64)
            class default
                ret = 0_8
                ret = 1_8/ret
        end select
        ret=modulo(ret,md)
    end function


    pure elemental function mint_to_int64(mx) result(ret)
        class(mint),intent(in):: mx
        integer(int64):: ret

        ret = to_int64(mx)
    end function

    pure elemental function to_modint(num) result(ret)
        class(*), intent(in):: num
        type(mint):: ret

        ret%val = to_int64(num)
    end function


    pure elemental subroutine mi_asgn(xm,y)
        type(mint), intent(inout) :: xm
        class(*), intent(in) :: y
        
        xm%val = to_int64(y)
    end subroutine


    pure elemental function mi_add(xm,y) result(ret)
        class(mint), intent(in) :: xm
        class(*), intent(in) :: y
        type(mint):: ret

        ret%val = modulo(xm%val + to_int64(y), md)
    end function


    pure elemental function mi_sub(xm,y) result(ret)
        class(mint), intent(in) :: xm
        class(*), intent(in) :: y
        type(mint):: ret

        ret%val = modulo(xm%val - to_int64(y), md)
    end function



    pure elemental function mi_mul(xm,y) result(ret)
        class(mint), intent(in) :: xm
        class(*), intent(in) :: y
        type(mint) ret

        ret%val = modulo(xm%val * to_int64(y), md)
    end function


    pure elemental function mi_div(xm,y) result(ret)
        class(mint), intent(in) :: xm
        class(*), intent(in) :: y
        type(mint):: ret

        ret%val = xm%val * to_int64(inv(to_modint(y)))
    end function

    
    pure elemental function inv(xm) result(ret)
        class(mint), intent(in) :: xm
        type(mint):: ret
        integer(int64) :: a, b, c, n
        integer(int64) :: x, y, z, m

        a = xm%val
        b = md
        c = 0_8
        n = 1_8
        do while (b /= 0_8)
            x = b
            y = mod(a,b)
            z = n-a/b*c
            m = c
            a = x
            b = y
            c = z
            n = m
        end do
        ret%val = n
    end function


    pure elemental function mi_pow(xm,y) result(ret)
        class(mint), intent(in) :: xm
        class(*), intent(in) :: y
        type(mint):: ret
        integer(int64) :: n
        type(mint) :: i

        ret%val = 1_8
        i%val = xm%val
        n = to_int64(y)
        do while (n > 0_8)
            if (btest(n,0)) ret%val = to_int64(mi_mul(ret,i))
            i%val = to_int64(mi_mul(i,i))
            n = rshift(n,1)
        end do
    end function

    pure type(mint) function dot_prod(x,y) result(ret)
        type(mint), intent(in) :: x(:), y(:)
        integer(int64):: i
        if (size(x,1) /= size(y,1)) i = to_int64('')
        do i = 1, size(x,1)
            call mi_asgn(ret,mi_add(ret,mi_mul(x(i),y(i))))
        end do
    end function


    pure function matmul1(x,y) result(ret)
        type(mint), intent(in) :: x(:,:), y(:)
        type(mint) :: ret(size(x,1))
        integer :: i
        do i = 1, size(x,1)
            call mi_asgn(ret(i),dot_prod(x(i,:),y))
        end do
    end function


    pure function matmul2(x,y) result(ret)
        type(mint), intent(in) :: x(:), y(:,:)
        type(mint) :: ret(size(y,2))
        integer :: i
        do i = 1, size(y,2)
            call mi_asgn(ret(i),dot_prod(x,y(:,i)))
        end do
    end function


    pure function matmul3(x,y) result(ret)
        type(mint), intent(in) :: x(:,:), y(:,:)
        type(mint) :: ret(size(x,1),size(y,2))
        integer :: i
        do i = 1, size(x,1)
            call mi_asgn(ret(i,:),matmul2(x(i,:),y))
        end do
    end function
end module mint_mod


module lazy_segtree_operators
    use mint_mod
    use,intrinsic :: iso_fortran_env
    implicit none
    type s_elem
        type(mint):: v,k
    end type
    type f_elem
        type(mint):: v
    end type
contains
    function f_same(f1,f2)
        type(f_elem),intent(in):: f1,f2
        logical:: f_same

        f_same = (f1%v%to_int() == f2%v%to_int())
    end function

    function e()
        type(s_elem):: e

        e = s_elem(mint(0),mint(1))
    end function


    function id()
        type(f_elem):: id

        id = f_elem(mint(0))
    end function


    function op(a,b)
        type(s_elem),intent(in):: a,b
        type(s_elem):: op
        
        op%v = a%v*a%k + b%v
        op%k = a%k*b%k
    end function


    function mapping(s,f) result(new_s)
        type(s_elem),intent(in):: s
        type(f_elem),intent(in):: f
        type(s_elem):: new_s
        type(mint):: inv9
        inv9 = inv(mint(9))

        ! print*, "mp"
        if (f_same(f,id())) then
            new_s%v = s%v
            new_s%k = s%k
        else
            new_s%v = ((s%k-1)*inv9)*f%v
            new_s%k = s%k
            ! print'(*(i0,1x))', new_s%v%to_int()
        end if
    end function


    function composition(old_f,f) result(new_f)
        type(f_elem),intent(in):: old_f,f
        type(f_elem):: new_f
        ! print*, "cps"
        if (f_same(f,id())) then
            new_f = old_f
        else
            new_f = f
        end if
    end function
end module

module lazy_segtree_mod
    use,intrinsic :: iso_fortran_env
    use lazy_segtree_operators
    implicit none

    type,public:: lazy_segtree
        type(s_elem),allocatable:: d(:)
        type(f_elem),allocatable:: lz(:)
        integer(int32):: len
    contains
        procedure:: leaf => lst_leaf
        procedure:: update => lst_update, lst_update_one
        procedure:: query => lst_query, lst_query_one
        procedure:: to_array => lst_to_array
        procedure:: set => lst_set
    end type
    interface lazy_segtree
        module procedure:: lst_init
    end interface
contains
    function lst_init(n) result(lst)
        type(lazy_segtree):: lst
        integer(int32),intent(in):: n
        integer(int32):: x

        lst%len = n

        x=1
        do while(n > x)
            x = 2*x
        end do
        allocate(lst%d(2*x-1), source=e())
        allocate(lst%lz(2*x-1),source=id())
    end function

    function lst_leaf(lst)
        class(lazy_segtree):: lst
        integer(int32):: lst_leaf

        lst_leaf = size(lst%d)/2+1
    end function


    subroutine lst_set(lst,i,s)
        class(lazy_segtree),intent(inout):: lst
        type(s_elem),intent(in):: s
        integer(int32),value:: i

        i=i+lst%leaf()-1
        lst%d(i) = s
        i=rshift(i,1)
        do while(i > 0)
            lst%d(i) = op(lst%d(i*2), lst%d(i*2+1))
            i=rshift(i,1)
        end do
    end subroutine


    subroutine lst_update_one(lst,i,f)
        class(lazy_segtree),intent(inout):: lst
        type(f_elem),intent(in):: f
        integer(int32),intent(in):: i

        call lst_update(lst,i,i,f)
    end subroutine


    subroutine lst_update(lst, l,r,f)
        class(lazy_segtree),intent(inout):: lst
        type(f_elem),intent(in):: f
        integer(int32),intent(in):: l,r
        
        call lst_update_sub(lst,l,r,f,1,lst%leaf(),1)
    end subroutine


    recursive subroutine lst_update_sub(lst,ql,qr,f,nl,nr,i)
        class(lazy_segtree),intent(inout):: lst
        integer(int32),intent(in):: ql,qr,nl,nr,i
        type(f_elem),intent(in):: f
        integer(int32):: nm
        
        ! print'(*(i0,1x))', ql,qr,nl,nr
        ! print'(*(i0,1x))', f%v%to_int()
        call eval(lst,i)
        if (ql <= nl .and. nr <= qr) then
            ! print*, "u",1
            lst%lz(i) = composition(lst%lz(i), f)
            call eval(lst,i)
        else if (ql <= nr .and. nl <= qr) then
            ! print*, "u",2
            nm = (nl+nr)/2
        !     call lst_update_sub(lst,ql,qr,f,nl,  nm,i*2  )
        !     call lst_update_sub(lst,ql,qr,f,nm+1,nr,i*2+1)
            lst%d(i) = op(lst%d(i*2), lst%d(i*2+1))
        end if
    end subroutine


    subroutine eval(lst,i)
        class(lazy_segtree):: lst
        integer(int32):: i

        ! print*, "ev", i
        if (f_same(lst%lz(i),id())) return
        if (i < lst%leaf()) then
            ! print*, "comp",i
            lst%lz(i*2) = composition(lst%lz(i*2), lst%lz(i))
            lst%lz(i*2+1) = composition(lst%lz(i*2+1), lst%lz(i))
        end if
        ! print'(a)', "mp"
        lst%d(i) = mapping(lst%d(i),lst%lz(i))
        ! print'(a)', "id"
        lst%lz(i) = id()
    end subroutine


    subroutine correct_laziness(lst)
        class(lazy_segtree):: lst
        integer(int32):: i
        
        do i=1,size(lst%d)
            call eval(lst,i)
        end do
    end subroutine


    function lst_query_one(lst,i) result(ret)
        class(lazy_segtree),intent(inout):: lst
        integer(int32),intent(in):: i
        type(s_elem):: ret

        ret = lst_query(lst,i,i)
    end function


    function lst_query(lst,l,r) result(ret)
        class(lazy_segtree),intent(inout):: lst
        integer(int32), intent(in):: l,r
        type(s_elem):: ret

        ret = lst_query_sub(lst,l,r,1,lst%leaf(),1)
    end function


    recursive function lst_query_sub(lst,ql,qr,nl,nr,i) result(ret)
        class(lazy_segtree),intent(inout):: lst
        integer(int32),intent(in):: ql,qr,nl,nr,i
        integer(int32):: nm
        type(s_elem):: ret,r1,r2
        
        call eval(lst,i)
        if (nr < ql .or. qr < nl) then
            ret = e()
        else if (ql <= nl .and. nr <= qr) then
            ret = lst%d(i)
        else
            nm = (nl+nr)/2
            r1 = lst_query_sub(lst,ql,qr,nl,  nm,i*2  )
            r2 = lst_query_sub(lst,ql,qr,nm+1,nr,i*2+1)
            ret = op(r1,r2)
        end if
    end function

    function lst_to_array(lst) result(ret)
        class(lazy_segtree):: lst
        type(s_elem):: ret(lst%len)

        call correct_laziness(lst)
        ret(:) = lst%d(lst%leaf():lst%leaf()+lst%len-1)
    end function


    subroutine debug_print(lst)
        class(lazy_segtree):: lst
        integer(int32):: l,r

        print'(a)', "datav"
        l=1; r=1
        do while(r <= size(lst%d))
            print'(*(i0,1x))', lst%d(l:r)%v%to_int()
            l=l*2; r=r*2+1
        end do

        print'(a)', "datak"
        l=1; r=1
        do while(r <= size(lst%d))
            print'(*(i0,1x))', lst%d(l:r)%k%to_int()
            l=l*2; r=r*2+1
        end do

        print'(a)', "lz"
        l=1; r=1
        do while(r <= size(lst%lz))
            print'(*(i0,1x))', lst%lz(l:r)%v%to_int()
            l=l*2; r=r*2+1
        end do
        

    end subroutine
end module

program main
    use,intrinsic :: iso_fortran_env
    use lazy_segtree_mod
    use lazy_segtree_operators
    implicit none
    integer(int32):: n,q,i
    integer(int32):: l,r,d
    type(lazy_segtree)::lst
    type(s_elem):: ans

    read*, n,q
    lst = lazy_segtree(n)
    do i=1,n
        ! print'(i0)', i
        call lst%set(i,s_elem(mint(1),mint(10)))
    end do

    do i=1,q
        read*, l,r,d
        print'(a)', "update"
        call lst%update(l,r,f_elem(mint(d)))
        ! call debug_print(lst)
        print'(a)', "query"
        ! ans = lst%query(1,n)
        ! print'(i0)', ans%v%to_int()
    end do
end program main