//#pragma GCC optimize ("Ofast")
//#pragma GCC target ("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#include "bits/stdc++.h"
using namespace std;
#define ll long long
#define pb push_back
#define all(_obj) _obj.begin(),_obj.end()
#define F first
#define S second
#define INF 1e18
#define pll pair<ll, ll> 
#define vll vector<ll>
ll n,m,a,b,c,k,temp,x,y;
const int MAXN=1e5+11,mod=998244353;
ll max(ll a,ll b) {return ((a>b)?a:b);}
ll min(ll a,ll b) {return ((a>b)?b:a);}
vll read(int n) {vll v(n);for (int i = 0; i < v.size(); i++)cin>>v[i];return v;}
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
ll p[2*MAXN],sp[2*MAXN];
class Segtree
{
    int n;
    long long int *lzy,*t;
    public:
    Segtree(int n,const vector<ll> &a)
    {
        lzy=new long long int[4*n];
        t=new long long int[4*n];
        this->n=n;
        maketree();
        build(a,1,0,n-1);
    }
    void maketree()
    {
    for(int i=0;i<4*n;i++)
    lzy[i]=-1,t[i]=0;
    }
    void build(const vector<ll> &a, int v, int tl, int tr) 
    {
        if (tl == tr) 
            t[v] = a[tl];
        else 
        {
            int tm = (tl + tr) / 2;
            build(a, v*2, tl, tm);
            build(a, v*2+1, tm+1, tr);
            t[v] = ((t[v*2]*p[tr-tm] % mod) + t[v*2+1])%mod;
        }
    }
    void updateRange(int node,int start,int end,int l,int r,ll val)
    {
    if(lzy[node] != -1)
    { 
        t[node] = sp[end - start] * lzy[node] % mod; 
        if(start != end)
        {
            lzy[node*2] = lzy[node];         
            lzy[node*2+1] = lzy[node];       
        }
        lzy[node] = -1;                             
    }
    if(start > end or start > r or end < l)
        return;
    if(start >= l and end <= r)
    {
        t[node] = sp[end-start] * val %mod;
        if(start != end)
        {
            lzy[node*2] = val;
            lzy[node*2+1] = val;
        }
        return;
    }
    int mid = (start + end) / 2;
    updateRange(node*2, start, mid, l, r, val);
    updateRange(node*2 + 1, mid + 1, end, l, r, val);
    t[node] = (t[node*2]*p[end-mid] % mod + t[node*2+1])%mod;
    }
        pll queryRange(int node, int start, int end, int l, int r)
    {
        if(start > end or start > r or end < l)
            return {0,0};
        if(lzy[node] != -1)
        {
            t[node] = sp[end - start] * lzy[node] % mod; 
            if(start != end)
            {
                lzy[node*2] = lzy[node];
                lzy[node*2+1] = lzy[node];
            }
            lzy[node] = -1;
        }
        if(start >= l and end <= r)           
            return {t[node],end-start+1};
        int mid = (start + end) / 2;
        pll p1 = queryRange(node*2, start, mid, l, r);
        pll p2 = queryRange(node*2 + 1, mid + 1, end, l, r);
        return {((p1.F*p[p1.S])%mod + p2.F)%mod,p1.S+p2.S};
    }
};
void sol(void)
{
p[0]=1;
sp[0]=1;
for(int i=1;i<2*MAXN;i++)
{
    p[i]=p[i-1]*10 % mod;
    sp[i]=(sp[i-1]+p[i])%mod;
}
int q;
cin>>n>>q;
vector<ll> a(n);
for(int i=0;i<n;i++) a[i]=1;
Segtree T(n,a);
while(q--)
{
    int l,r,d;
    cin>>l>>r>>d;
    l--;r--;
    T.updateRange(1,0,n-1,l,r,d);
    cout<<T.queryRange(1,0,n-1,0,n-1).F<<'\n';
}
return ;
}
int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
    int test=1;
    //cin>>test;
    for(int i=1;i<=test;i++)
    sol();
}


Measured memory_bytes: 20420