#pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
#include <iostream>
using namespace std;

#define int long long int
#define all(x) (x).begin(), (x).end()
#define removeDuplicates(a) a.resize(unique(all(a))-a.begin())
#define endl '\n'

const int mod=998244353;

int power(int a,int p){
	int ans=1;
	int mul=a%mod;
	while(p){
		if(p%2==1){
			ans=((ans%mod)*(mul%mod))%mod;
			ans%=mod;
		}
		mul=((mul%mod)*(mul%mod))%mod;
		mul%=mod;
		p>>=1;
	}
	return ans%mod;
}

class segtree{
	int sz;
	vector<int>val;
	vector<int>opt;
	vector<int>cnt;
	int NOP=-1;
	int NEU=0;

public:

	segtree (int n){
		sz=1;
		while(sz<n){
			sz = sz*2;
		}
		val.assign(2*sz,1LL);
		opt.assign(2*sz,NOP);
		cnt.assign(2*sz,0LL);
	}

	void build(int n,int curr,int left,int right){
		if(right-left==1){ 
			if(left<n){
				cnt[curr]=power(10,n-1-left)%mod;
				val[curr]=1LL*cnt[curr];
			}
			return;
		}
		int mid=(left+right)/2;
		build(n,2*curr+1,left,mid);
		build(n,2*curr+2,mid,right);
		cnt[curr]=(cnt[2*curr+1]%mod+cnt[2*curr+2]%mod)%mod;
		val[curr]=(val[2*curr+1]%mod+val[2*curr+2]%mod)%mod;
	}
	void build(int n){
		build(n,0,0,sz);
	}

	void propogate(int curr,int left,int right){
		if((right-left)==1){
			return;
		}
		if(opt[curr]!=NOP){
			opt[2*curr+1]=(opt[curr])%mod;
			val[2*curr+1]=((opt[curr]%mod)*(cnt[2*curr+1]%mod))%mod;
			opt[2*curr+2]=(opt[curr])%mod;
			val[2*curr+2]=((opt[curr]%mod)*(cnt[2*curr+2]%mod))%mod;
			opt[curr]=NOP;
		}
	}

	void updateRange(int l,int r,int value,int curr,int left,int right){
		if(left>=r || right<=l){
			return;
		}
		propogate(curr,left,right);
		if(left>=l && right<=r){
			opt[curr]=value%mod;
			val[curr]=((value%mod)*(cnt[curr]%mod));
			return;
		}
		int mid=(left+right)/2;
		updateRange(l,r,value,2*curr+1,left,mid);   
		updateRange(l,r,value,2*curr+2,mid,right);
		val[curr]=(val[2*curr+1]+val[2*curr+2])%mod;
	}
	void updateRange(int l,int r,int value){
		updateRange(l,r,value,0,0,sz);
	}

	// void updateIndex(int i,int value,int curr,int left,int right){
	// 	if(right-left==1){
	// 		opt[curr]+=value;
	// 		val[curr]+=value*cnt[curr];
	// 		return;
	// 	}
	// 	int mid=(left+right)/2;
	// 	if(i<mid){
	// 		updateIndex(i,value,2*curr+1,left,mid);
	// 	}else{
	// 		updateIndex(i,value,2*curr+2,mid,right);
	// 	}   
	// 	val[curr]=val[2*curr+1]+val[2*curr+2];
	// }
	// void updateIndex(int i,int value){
	// 	updateIndex(i,value,0,0,sz);
	// }

	// int queryIndex(int i,int curr,int left,int right){
	// 	if(right-left==1){
	// 		return val[curr];
	// 	}		
	// 	propogate(curr,left,right);
	// 	int mid=(left+right)/2;
	// 	if(i<mid){
	// 		return queryIndex(i,2*curr+1,left,mid);
	// 	}else{
	// 		return queryIndex(i,2*curr+2,mid,right);
	// 	}
	// }
	// int queryIndex(int i){
	// 	return queryIndex(i,0,0,sz);
	// }

	int queryRange(int l,int r,int curr,int left,int right){
		if(left>=r || right<=l){
			return NEU;
		}
		propogate(curr,left,right);
		if(left>=l && right<=r){
			return val[curr]%mod;
		}
		int mid=(left+right)/2;
		int c1=(queryRange(l,r,2*curr+1,left,mid)%mod);
		int c2=(queryRange(l,r,2*curr+2,mid,right)%mod);
		return (c1%mod+c2%mod)%mod;
	}
	int queryRange(int l,int r){
		return queryRange(l,r,0,0,sz)%mod;
	}
};

void solve(){
	int n,q;
	cin>>n>>q;
	segtree st(n);
	st.build(n);
	for(int i=0;i<q;i++){
		int l,r,d;
		cin>>l>>r>>d;
		l--;
		st.updateRange(l,r,d);
		cout<<st.queryRange(0,n)<<endl;
	}
}

int32_t main(){

	//remove for interactive problems
	ios_base::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);

	solve();
	cerr<<"Time : "<<1000*((double)clock())/(double)CLOCKS_PER_SEC<<"ms\n";

	return 0;
}

Measured memory_bytes: 15628