#include<bits/stdc++.h>
#include<iostream>
using namespace std;
#define int long long int
#define ld long double
#define all(x) (x).begin(), (x).end()
#define fi first
#define se second
#define removeDuplicates(a) a.resize(unique(all(a))-a.begin())
#define endl '\n'	
#define setbits(x) (__builtin_popcount(x))
int mod=998244353;
int INF64=mod*mod+1;
const int c=443664157;

vector<int> p(200001);

void precalc(){
	p[0]=1;
	for(int i=1;i<=200000;i++)
		p[i]=(p[i-1]*10)%mod;
}

int power(int y){
	return p[y];
}

class segTree{
	int sz;
	int n;
	vector<int> val;
	vector<int> opt;
	vector<int> len;
	int NOP=0;
	int NEU=0;

public:
	segTree(int n){
		this->n=n;
		sz=1;
		while(sz<n)	sz*=2;
		val.assign(2*sz,0LL);
		opt.assign(2*sz,NOP);
		len.assign(2*sz,0LL);
	}

	void build(int x, int lx, int rx){
		if(rx==lx){ 
			if(lx<n){
				len[x]=1;
				val[x]=power(n-1-lx);
			}
			return;
		}

		int m=(lx+rx)/2;
		build(2*x+1,lx,m);
		build(2*x+2,m+1,rx);
		len[x]=len[2*x+1]+len[2*x+2];
		val[x]=(val[2*x+1]+val[2*x+2])%mod;
	}

	void build(){
		build(0,0,sz);
	}

	void propogate(int x, int lx, int rx){
		if(lx==rx||opt[x]==NOP)	return;

		int m=(lx+rx)/2;
		opt[2*x+1]=opt[x];
		val[2*x+1]=(((opt[x]*(c*power(n-m-1))%mod)%mod)*(power(len[2*x+1])-1+mod)%mod)%mod;
		opt[2*x+2]=opt[x];
		val[2*x+2]=(((opt[x]*(c*power(n-rx-1))%mod)%mod)*(power(len[2*x+1])-1+mod)%mod)%mod;
		opt[x]=NOP;
	}

	void updateRange(int l, int r, int v, int x, int lx, int rx){
		propogate(x,lx,rx);
		if(lx>r||l>rx)	return;
		if(lx>=l&&rx<=r){
			opt[x]=v;
			int res=((v*(c*power(n-rx-1))%mod)%mod)*(power(len[x])-1+mod)%mod;
			val[x]=res%mod;
			return;
		}

		int m=(lx+rx)/2;
		updateRange(l,r,v,2*x+1,lx,m);   
		updateRange(l,r,v,2*x+2,m+1,rx);
		
		val[x]=(val[2*x+1]+val[2*x+2])%mod;
	}

	void updateRange(int l, int r, int v){
		updateRange(l,r,v,0,0,sz);
	}

	void updateIndex(int i, int v, int x, int lx, int rx){
		if(rx==lx){
			opt[x]+=v;
			val[x]+=v*len[x];
			return;
		}

		int m=(lx+rx)/2;
		if(i<=m)
			updateIndex(i,v,2*x+1,lx,m);
		else
			updateIndex(i,v,2*x+2,m+1,rx);

		val[x]=val[2*x+1]+val[2*x+2];
	}

	void updateIndex(int i, int v){
		updateIndex(i,v,0,0,sz);
	}

	int queryIndex(int i, int x, int lx, int rx){
		propogate(x,lx,rx);
		if(rx==lx)	return val[x];

		int m=(lx+rx)/2;
		if(i<m)
			return queryIndex(i,2*x+1,lx,m);
		else
			return queryIndex(i,2*x+2,m+1,rx);
	}
	
	int queryIndex(int i){
		return queryIndex(i,0,0,sz);
	}

	int queryRange(int l, int r, int x, int lx, int rx){
		propogate(x,lx,rx);
		if(lx>r||l>rx)	return NEU;
		if(lx>=l&&rx<=r)	return val[x];

		int m=(lx+rx)/2;
		int c1=queryRange(l,r,2*x+1,lx,m);
		int c2=queryRange(l,r,2*x+2,m+1,rx);
		
		return c1+c2;
	}

	int queryRange(int l, int r){
		return queryRange(l,r,0,0,sz);
	}

	int get(){
		return val[0];
	}
};

void solve(){
	int n,q;
	cin>>n>>q;
	precalc();
	segTree st(n);
	st.build();

	while(q--){
		int l,r,d;
		cin>>l>>r>>d;
		st.updateRange(l-1,r-1,d);
		cout<<st.get()<<endl;
	}
}

int32_t main(){
	
	ios_base::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);

	int T;
	// cin>>T;
	T=1;
	for(int i=1;i<=T;i++){
		// cout<<"Case #"<<i<<": ";
		solve();
	}
	cerr<<"Time : "<<1000*((double)clock())/(double)CLOCKS_PER_SEC<<"ms\n";
}

Measured memory_bytes: 17212