#include <bits/stdc++.h>
#define rep(i,n)for(int i=0;i<(n);i++)
using namespace std;
typedef long long ll;
typedef pair<int,int>P;

const int MOD=998244353;
const int INF=0x3f3f3f3f;
const ll INFL=0x3f3f3f3f3f3f3f3f;

/*
#include <atcoder/segtree>
using namespace atcoder;
*/

template<class T,class U>
class LazySegtree{
	int n;
	vector<T>dat;
	vector<U>lazy;
	T INIT;
	T E0;
	U E1;
	function<T(T,U,int)>F0;
	function<U(U,U)>F1;
	function<T(T,T)>F2;
public:
	LazySegtree(int n_,T INIT,T E0,U E1
	,function<T(T,U,int)>F0,function<U(U,U)>F1,function<T(T,T)>F2):
		INIT(INIT),E0(E0),E1(E1),F0(F0),F1(F1),F2(F2){
		n=1;while(n<n_)n<<=1;
		dat=vector<T>(2*n,INIT);
		for(int i=n-2;i>=0;i--){
			dat[i]=F2(dat[i*2+1],dat[i*2+2]);
		}
		lazy=vector<U>(2*n,E1);
	}
	inline void push(int k,int s){
		if(lazy[k]==E1)return;
		dat[k]=F0(dat[k],lazy[k],s);
		if(k<n-1){
			lazy[k*2+1]=F1(lazy[k*2+1],lazy[k]);
			lazy[k*2+2]=F1(lazy[k*2+2],lazy[k]);
		}
		lazy[k]=E1;
	}
	inline void upnode(int k){
		dat[k]=F2(dat[k*2+1],dat[k*2+2]);
	}
	inline void update(int a,int b,U x,int k,int l,int r){
		push(k,r-l);
		if(r<=a||b<=l)return;
		if(a<=l&&r<=b){
			lazy[k]=F1(lazy[k],x);
			push(k,r-l);
			return;
		}
		update(a,b,x,k*2+1,l,(l+r)/2);
		update(a,b,x,k*2+2,(l+r)/2,r);
		upnode(k);
	}
	inline T query(int a,int b,int k,int l,int r){
		push(k,r-l);
		if(b<=l||r<=a)return E0;
		if(a<=l&&r<=b)return dat[k];
		T lb=query(a,b,k*2+1,l,(l+r)/2);
		T rb=query(a,b,k*2+2,(l+r)/2,r);
		upnode(k);
		return F2(lb,rb);
	}
	inline void update(int a,int b,U x){
		update(a,b,x,0,0,n);
	}
	inline void update(int a,U x){
		update(a,a+1,x);
	}
	inline T query(int a,int b){
		return query(a,b,0,0,n);
	}
	inline T query(int a){
		return query(a,a+1);
	}
};

template<class T>
class RAQ_RMQ:public LazySegtree<T,T>{
public:
	RAQ_RMQ(int n_,T INIT,T E0,function<T(T,T)>F2=[](T a,T b){return min(a,b);})
	:LazySegtree<T,T>(n_,INIT,E0,0,
	[](T a,T b,int s){return a+b;},
	[](T a,T b){return a+b;},
	F2){}
};

template<class T>
class RAQ_RSQ:public LazySegtree<T,T>{
public:
	RAQ_RSQ(int n_,T INIT,T E0)
	:LazySegtree<T,T>(n_,INIT,E0,0,
	[](T a,T b,int s){return a+b*s;},
	[](T a,T b){return a+b;},
	[](T a,T b){return a+b;}){}
};

template<class T>
class RUQ_RMQ:public LazySegtree<T,T>{
public:
	RUQ_RMQ(int n_,T INIT,T E0,function<T(T,T)>F2=[](T a,T b){return min(a,b);})
	:LazySegtree<T,T>(n_,INIT,E0,numeric_limits<T>::min(),
	[](T a,T b,int s){return b;},
	[](T a,T b){return b;},
	F2){}
};

template<class T>
class RUQ_RSQ:public LazySegtree<T,T>{
public:
	RUQ_RSQ(int n_,T INIT,T E0)
	:LazySegtree<T,T>(n_,INIT,E0,numeric_limits<T>::min(),
	[](T a,T b,int s){return b*s;},
	[](T a,T b){return b;},
	[](T a,T b){return a+b;}){}
};

ll Pow[300000];
ll Powsum[300000];

struct st{
	ll num,dig;
};
int main(){
	Pow[0]=Powsum[0]=1;
	for(int i=1;i<300000;i++)Pow[i]=Pow[i-1]*10%MOD;
	for(int i=1;i<300000;i++)Powsum[i]=(Powsum[i-1]+Pow[i])%MOD;

	int n,q;cin>>n>>q;
	LazySegtree<st,int>seg(n,{1,1},{0,0},-1,
	[&](st a,int b,int s){
		return (st){Powsum[s-1]*b%MOD,s};
	},
	[](int a,int b){return b;},
	[&](st a,st b){
		return (st){(a.num*Pow[b.dig]+b.num)%MOD,a.dig+b.dig};
	});
	rep(i,q){
		int l,r,d;scanf("%d%d%d",&l,&r,&d);l--;
		seg.update(l,r,d);
		printf("%lld\n",seg.query(0,n).num);
	}
}

Measured memory_bytes: 18192