// Problem : E - Replace Digits
// Contest : AtCoder - ACL Beginner Contest
// URL : https://atcoder.jp/contests/abl/tasks/abl_e
// Memory Limit : 1024 MB
// Time Limit : 2000 ms
// Powered by CP Editor (https://github.com/cpeditor/cpeditor)

//#pragma GCC optimize("Ofast")
//#pragma GCC optimize ("unroll-loops")
//#pragma GCC target("avx,avx2,fma")
#include<bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define eb emplace_back
#define pb push_back
#define size(s) (int)s.size()
#define int long long
#define INF 1000000000000000000
#define vi vector<int>
#define vs vector<string>
#define vv vector<vector<int>>
#define pii pair<int,int>
#define m_p(x,y) make_pair(x,y)
#define vp vector<pair<int,int>>
#define setbits(x) __builtin_popcountll(x)
#define f first
#define se second
#define inc(v,n,x) v.assign(n,x)
#define incd(v,n) v.resize(n)
#define iniz(n) memset(n,0,sizeof(n))
#define inin(n) memset(n,-1,sizeof(n))
#define inimi(n) memset(n,0xc0,sizeof(n))
#define inima(n) memset(n,0x3f,sizeof(n))
#define all(v) (v).begin(),(v).end()

using namespace std;

template<typename T1,typename T2>istream &operator>>(istream &is, vector<pair<T1,T2>> &v) { for (pair<T1,T2> &t : v) is >> t.f>>t.se; return is; }
template<typename T>istream &operator>>(istream &is, vector<T> &v) { for (T &t : v) is >> t; return is; }
template<typename T>ostream &operator<<(ostream &os, const vector<T> &v) { for (const T &t : v) {os << t <<" ";} os << '\n'; return os; }

const int N=200001;
double pi=acos(-1.0);
int md=998244353;
int dx1[]={0,0,-1,1};
int dy1[]={1,-1,0,0};
//const int N=2e5;
int arr[N];
int Tree[4*N+1];
int lazy[4*N+1];
int pre_arr[N];
template<class T>
T abst(T a)
{return a<0?-a:a;}
void build_max(int node,int start,int end){
	if(start==end){
		Tree[node]=arr[start];
		return;
	}
	int mid=((start+end)>>1);
	build_max(2*node+1,start,mid);
	build_max(2*node+2,mid+1,end);
	//According to the question,change from here
	Tree[node]=(Tree[2*node+1]+Tree[2*node+2])%md;
}
void update_max(int node,int start,int end,int l,int r,int val){
	
	if(lazy[node] != 0)
    { 
        // This node needs to be updated
        int sum=pre_arr[end];
        if(start-1>=0)
        {
        	sum-=pre_arr[start-1];
        	sum+=md;
        	sum%=md;
        }
        Tree[node] = (sum*lazy[node])%md;    // Update it
        if(start != end)
        {
            lazy[node*2+1] = lazy[node];                  // Mark child as lazy
            lazy[node*2+2] = lazy[node];                // Mark child as lazy
        }
        lazy[node] = 0;                                  // Reset it
    }
    
	 if (start > end or start > r or end < l)
        return;
	
	if(start >= l and end <= r)
    {
        // Segment is fully within range
       int sum=pre_arr[end];
        if(start-1>=0)
        {
        	sum-=pre_arr[start-1];
        	sum+=md;
        	sum%=md;
        }
        Tree[node] = (sum*val)%md;
        if(start != end)
        {
            // Not leaf node
            lazy[node*2+1] = val;
            lazy[node*2+2] = val;
        }
        return;
    }
	int mid = (start + end) / 2;
    update_max(node*2+1, start, mid, l, r, val);        // Updating left child
    update_max(node*2 + 2, mid + 1, end, l, r, val);   // Updating right child
    Tree[node] = (Tree[node*2+1] + Tree[node*2+2])%md;
}
int query_max(int node,int start,int end,int l,int r){ 
if(lazy[node] != 0)
    { 
        // This node needs to be updated
        int sum=pre_arr[end];
        if(start-1>=0)
        {
        	sum-=pre_arr[start-1];
        	sum+=md;
        	sum%=md;
        }
        Tree[node] = (sum*lazy[node])%md;    // Update it
        if(start != end)
        {
            lazy[node*2+1] = lazy[node];                  // Mark child as lazy
            lazy[node*2+2] = lazy[node];                // Mark child as lazy
        }
        lazy[node] = 0;                                  // Reset it
    }
	if(start>end||end<l||start>r)
		return 0;//0 in case of sum , high value in case of min , low value in case of max and soooo on 
	if(start>=l&&end<=r)
		return(Tree[node]);
	int mid = (start+end)/2 ; 
	int p1 = query_max(node*2+1, start, mid, l,r);
	int p2 = query_max(node*2+2, mid+1, end , l,r);
	return (p1+p2)%md;
}
void solve()
{
	int n,q;
	cin>>n>>q;
	arr[n-1]=1;
	//inin(lazy);
	for(int i=n-2;i>=0;i--)
	{
		arr[i]=arr[i+1]*10%md;
	}
	pre_arr[0]=arr[0];
	for(int i=1;i<=n;i++)
	pre_arr[i]=(arr[i]+pre_arr[i-1])%md;
	
	build_max(0,0,n-1);
	while(q--)
	{
		int l,r,d;
		cin>>l>>r>>d;
		update_max(0,0,n-1,l-1,r-1,d);
		cout<<query_max(0,0,n-1,0,n-1)<<"\n";
	}
	
}

int32_t main(){
ios_base::sync_with_stdio(0);cin.tie(NULL);cout.tie(NULL);
int t=1;
//cin>>t;
for(int i=1;i<=t;i++)
{
    solve();
}
return 0;
}


Measured memory_bytes: 15004