#include<iostream>
#include<vector>
#include<algorithm>
#include<set>
#include<map>
#include<queue>
#include<cmath>
#include<iomanip>
#include<cstring>
#include<complex>
#include<cstdio>
#define initdp(a,b) for(int i=0;i<=a;i++)for(int j=0;j<=b;j++)dp[i][j]=-1;
#define fi first
#define se second
#define pb push_back
#define pii pair<int,int>
#define ppi pair<pii,int>
#define pip pair<int,pii>
#define ll long long
#define pll pair<ll,ll>
#define rep(i,n) for(int i=0;i<n;i++)
#define repd(i,n) for(int i=n-1;i>=0;i--)
#define inf 1000000001
#define inf1 1000000000000000001
#define mod 998244353
#define pie 3.14159265358979323846
#define N 200005
#define mid(l,r) l+(r-l)/2
using namespace std;
int dx[4]={1,0,-1,0},dy[4]={0,1,0,-1};
int ddx[8]={1,1,0,-1,-1,-1,0,1},ddy[8]={0,1,1,1,0,-1,-1,-1};
void mad(ll &a,ll b){a=(a+b)%mod;if(a<0)a+=mod;}
ll gcd(ll a,ll b){ if(!a)return b;return gcd(b%a,a);}
ll tree[4*N],lazy[4*N];
ll n,q;
ll ten[N];
ll get(int l,int r){
	return (ten[l]-ten[r+1]+mod)%mod;
	if(l==0)return ten[r];
	else return (ten[r]-ten[l-1]+mod)%mod;
}
void updateRange(int node, int start, int end, int l, int r, ll val)
{
    if(lazy[node] != 0)
    { 
        // This node needs to be updated
        tree[node] = (lazy[node]*get(start,end))%mod;    // Update it
        if(start != end)
        {
            lazy[node*2] = lazy[node];                  // Mark child as lazy
            lazy[node*2+1] = lazy[node];                // Mark child as lazy
        }
        lazy[node] = 0;                                  // Reset it
    }
    if(start > end or start > r or end < l)              // Current segment is not within range [l, r]
        return;
    if(start >= l and end <= r)
    {
        // Segment is fully within range
        tree[node] = (val*get(start,end))%mod;
        if(start != end)
        {
            // Not leaf node
            lazy[node*2] = val;
            lazy[node*2+1] = val;
        }
        return;
    }
    int mid = (start + end) / 2;
    updateRange(node*2, start, mid, l, r, val);        // Updating left child
    updateRange(node*2 + 1, mid + 1, end, l, r, val);   // Updating right child
    tree[node] = (tree[node*2] + tree[node*2+1])%mod;        // Updating root with max value 
}

ll queryRange(int node, int start, int end, int l, int r)
{
    if(start > end or start > r or end < l)
        return 0;
    if(lazy[node] != 0)
    { 
        // This node needs to be updated
        tree[node] = (lazy[node]*get(start,end))%mod;    // Update it
        if(start != end)
        {
            lazy[node*2] = lazy[node];                  // Mark child as lazy
            lazy[node*2+1] = lazy[node];                // Mark child as lazy
        }
        lazy[node] = 0;                                  // Reset it
    }
    if(start >= l and end <= r)             // Current segment is totally within range [l, r]
        return tree[node];
    int mid = (start + end) / 2;
    ll p1 = queryRange(node*2, start, mid, l, r);         // Query left child
    ll p2 = queryRange(node*2 + 1, mid + 1, end, l, r); // Query right child
    return (p1 + p2)%mod;
}
void solve(){
	cin>>n>>q;
	ten[0]=1;
	for(int i=1;i<n;i++)ten[i]=(ten[i-1]*10)%mod;
	for(int i=1;i<n;i++){
		ten[i]=(ten[i]+ten[i-1])%mod;
		//cout<<ten[i]<<" ";
	}//cout<<"\n";
	reverse(ten,ten+n);
	for(int i=0;i<n;i++)updateRange(1,0,n-1,i,i,1);
	//cout<<queryRange(1,0,n-1,0,n-1)<<"\n";
	for(int i=0;i<q;i++){
		int l,r,d;
		cin>>l>>r>>d;
		l--;
		r--;
		updateRange(1,0,n-1,l,r,d);
		cout<<queryRange(1,0,n-1,0,n-1)<<"\n";
	}
}
int main()
{
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);
	int t;
	//cin>>t;
	t=1;
	while(t--){
		solve();
	}
}

Measured memory_bytes: 13376