//#pragma GCC         optimize("O3")
#pragma GCC optimize("Ofast")
#pragma GCC target("avx,avx2,fma")
#pragma GCC optimization ("unroll-loops")
#include            <bits/stdc++.h>
#include            <ext/pb_ds/assoc_container.hpp>
#include            <ext/pb_ds/tree_policy.hpp>
#define FastIO      ios_base::sync_with_stdio(0);cin.tie(0),cout.tie(0)
#define pb          push_back
#define eb          emplace_back
#define mp          make_pair
#define mem(x,i)    memset(x,i,sizeof(x))
#define ff          first
#define ss          second
#define popcount(x) __builtin_popcount(x)
#define all(x)      x.begin(),x.end()
#define Case(t)     for(int ks=1;ks<=t;ks++)
#define fileout     freopen("output.txt","w",stdout)
#define filein      freopen("input.txt","r",stdin)
#define D(x)        cerr<< __LINE__ <<": "<< #x << " = "<<(x) <<'\n';
#define E(x,y)      cerr<< __LINE__ <<": "<< #x << " = "<<(x)<<' '<< #y << " = "<<(y) <<'\n';
#define endl        '\n'
///Input-Output
#define si(x)       scanf("%d",&x)
#define sii(x,y)     scanf("%d%d",&x,&y)
#define sl(x)       scanf("%lld",&x)
#define sll(x,y)     scanf("%lld%lld",&x,&y)
///
using namespace std;
using namespace __gnu_pbds;

using ll  = long long;
using ld  = long double;
using ull = unsigned long long;
using pii = pair<int,int>;
using pll = pair<ll,ll>;
using pil = pair<int,ll>;


const int INF    = 0x3f3f3f3f;
const ll LL_INF  = 0x3f3f3f3f3f3f3f3f;
const double PI  = acos(-1.0);
const double eps = 1e-8;
const int mod    = 998244353;
const int mx     = 200005;
const int lg     = 26;

template <typename T>  using orderedSet =
    tree<T, null_type, less_equal<T>,
    rb_tree_tag, tree_order_statistics_node_update>;//find_by_order,order_of_key*/

/*------------------------------Graph Moves----------------------------*/
//const int fx[]= {+1,-1,+0,+0};
//const int fy[]= {+0,+0,+1,-1};
//const int fx[]={+0,+0,+1,-1,-1,+1,-1,+1};   // Kings Move
//const int fy[]={-1,+1,+0,+0,+1,+1,-1,-1};  // Kings Move
//const int fx[]={-2, -2, -1, -1,  1,  1,  2,  2};  // Knights Move
//const int fy[]={-1,  1, -2,  2, -2,  2, -1,  1}; // Knights Move
/*---------------------------------------------------------------------*/

ll powmod(ll a,ll b){ll res=1;a%=mod;assert(b>=0);for(; b; b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
/*----------------------BitMask-----------------------------------------*/
//inline int setBit(int N,int pos){return N=N | (1<<pos);}
//inline int resetBit(int N,int pos){return N= N & ~(1<<pos);}
//inline bool checkBit(int N,int pos){return (bool) (N& (1<<pos));}


///----------------Start------------------///
struct SegmentTree
{
    ///Change data according to problem
    struct data
    {
        ll pVal;
        ll tVal;
        int dig;
        data(){};
    };
    int N;
    vector<data>st;
    vector<bool>isLazy;
    vector<int>lazy;

    void init(int n)
    {
        N=n;
        st.resize(4*N+5);
        isLazy.assign(4*N+5,false);
        lazy.assign(4*N+5,0);
    }
    ///Merge the child according to problem
    void merge(data &cur,data &l,data &r)
    {
        cur.pVal = (l.pVal+r.pVal)%mod;
    }
    void propagate(int C,int L,int R)
    {
        if(L!=R)
        {
            isLazy[C<<1]=1;
            isLazy[C<<1|1]=1;
            lazy[C<<1]=lazy[C];
            lazy[C<<1|1]=lazy[C];
        }
        st[C].pVal = (lazy[C]*st[C].tVal)%mod;
        st[C].dig = lazy[C];
        lazy[C]=0;
        isLazy[C]=false;
    }
    void build(int C,int L,int R)
    {
        if(L==R)
        {
            st[C].dig=1;
            st[C].pVal = powmod(10,N-L);
            st[C].tVal = st[C].pVal;
            return ;
        }
        int M =(L+R)>>1;
        build(C<<1,L,M);
        build(C<<1|1,M+1,R);
        merge(st[C],st[C<<1],st[C<<1|1]);
        st[C].tVal = st[C].pVal;
    }
    data Query(int C,int L,int R,int i,int j)
    {
        if(isLazy[C]) propagate(C,L,R);
        if(j<L || i>R) return data();
        if(i<=L && R<=j) return st[C];
        int M =(L+R)>>1;
        data left = Query(C<<1,L,M,i,j);
        data right = Query(C<<1|1,M+1,R,i,j);
        data cur;merge(cur,left,right);
        return cur;
    }
    data pQuery(int C,int L,int R,int idx)
    {
        if(isLazy[C]) propagate(C,L,R);
        if(L==R) return st[C];
        int M = (L+R)>>1;
        if(idx<=M) return pQuery(C<<1,L,M,idx);
        else return pQuery(C<<1|1,M+1,R,idx);
    }
    void Update(int C,int L,int R,int i,int j,int val)
    {
        if(isLazy[C]) propagate(C,L,R);
        if(j<L || i>R) return ;
        if(i<=L && R<=j)
        {
            isLazy[C]=1;
            lazy[C] = val;
            propagate(C,L,R);
            return ;
        }
        int M=(L+R)>>1;
        Update(C<<1,L,M,i,j,val);
        Update(C<<1|1,M+1,R,i,j,val);
        merge(st[C],st[C<<1],st[C<<1|1]);
    }
    void pUpdate(int C,int L,int R,int idx,int val)
	{
		if(isLazy[C])
			propagate(C, L, R);
		if(L == R)
		{
			isLazy[C] = 1;
			lazy[C] = val;
			propagate(C, L, R);
			return;
		}
		int M = (L + R)>>1;
		if(idx <= M)
			pUpdate(C<<1,L,M,idx,val);
		else
			pUpdate(C<<1|1,M+1,R,idx,val);
		merge(st[C], st[C<<1], st[C<<1|1]);
	}

	data query(int idx)
	{
		return pQuery(1,1,N,idx);
	}

	data query(int l, int r)
	{
		return Query(1,1,N,l, r);
	}

	void update(int idx, int val)
	{
		pUpdate(1,1,N,idx, val);
	}
	void update(int l, int r, int val)
	{
		Update(1,1,N,l, r, val);
	}
};

int main()
{
    int n,q;
    sii(n,q);
    SegmentTree ST;
    ST.init(n);
    ST.build(1,1,n);
    while(q--)
    {
        int l,r,val;
        sii(l,r);si(val);
        ST.update(l,r,val);
        ll ans = ST.query(1,n).pVal;
        printf("%lld\n",ans);
    }
}


Measured memory_bytes: 18848