//#pragma warning(disable:4996)
//#include <Windows.h>
#include <iostream>
#include <vector>
#include <limits.h>
#include <algorithm>
#include <string>
#include <math.h>
#include <limits.h>
#include <queue>
#include <map>
#include <set>
#include <iomanip>
#include <bitset>
#include <cassert>
#include <random>
#include <functional>
#include <stack>
#include <iomanip>
#include <cassert>
//#include <boost/multiprecision/cpp_int.hpp>
#include <complex>
#include <cstdio>
#include <list>
#include <bitset>
//#include <stdio.h>

//< in.txt > out.txt
using namespace std;
//std::ios::sync_with_stdio(false);
//std::cin.tie(0);
const long long MOD = 1e9 + 7;
const long long INF = 1e18;
typedef long long LL;
typedef long double LD;
//typedef boost::multiprecision::cpp_int bigint;
typedef pair<LL, LL> PLL;
typedef pair<int, int> PI;
typedef pair<LD, LL> pdl;
typedef pair<LD, LD> pdd;
typedef vector<LL> VLL;
typedef vector<VLL> VVLL;
typedef vector<int> VI;
typedef vector<vector<int>> VVI;
typedef unsigned long long ULL;
template<class T>
using pqueue = priority_queue<T, vector<T>, function<bool(T, T)>>;

template<class T>
inline void chmin(T& a, T b) {
	a = min(a, b);
}

template<class T>
inline void chmax(T& a, T b) {
	a = max(a, b);
}

void input();
void solve();

void daminput();
void naive();

void outputinput();

int main() {
	std::cin.tie(0);
	std::ios::sync_with_stdio(false);
	input();
	//daminput();
	solve();
	//naive();
	//outputinput();
	return 0;
}

//////////////////////////////////////////////////
//////////////////////////////////////////////////

int N, Q;
VLL L, R, D;
LL mod = 998244353;

void input() {
	cin >> N >> Q;
	L.resize(Q);
	R.resize(Q);
	D.resize(Q);
	for (int q = 0; q < Q; q++)cin >> L[q] >> R[q] >> D[q];
}

void daminput() {
}

//TT(T,T):=モノイドの乗算
//MT(M,T,LL):=モノイドに対する左作用(第3項は要素数)
//MM(M,M):=左作用の合成
template<class T, class M>
class LazySegtree {
public:
	vector<T> seg;
	vector<M> lazy;   //実、更新の必要性
	typedef function<T(T, T)> TT;
	typedef function<T(M, T, int)> MT;
	typedef function<M(M, M)> MM;
	TT tt;
	MT mt;
	MM mm;
	M Me;
	T Te;
	int snum;   //何回シフトで下段から1に行けるか
	LazySegtree(int N, TT _tt, MT _mtn, MM _mm, T te, M me) {
		int RN = 1;
		snum = 0;
		while (RN < N) {
			RN *= 2;
			snum++;
		}
		Te = te;
		Me = me;
		seg.resize(2 * RN, Te);
		lazy.resize(2 * RN, Me);
		tt = _tt;
		mt = _mtn;
		mm = _mm;
	}
	LazySegtree(vector<T>& vec, TT _tt, MT _mt, MM _mm, T te, M me) {
		int RN = 1;
		snum = 0;
		while (RN < vec.size()) {
			RN *= 2;
			snum++;
		}
		Te = te;
		Me = me;
		seg.resize(2 * RN, Te);
		lazy.resize(2 * RN, Me);
		tt = _tt;
		mt = _mt;
		mm = _mm;
		for (int n = 0; n < vec.size(); n++) seg[RN + n] = vec[n];
		for (int n = RN - 1; n >= 1; n--) {
			seg[n] = tt(seg[2 * n], seg[2 * n + 1]);
		}
	}
	void eval(int k, int l, int r) {
		if (k >= seg.size())return;
		if (lazy[k] == Me)return;
		seg[k] = mt(lazy[k], seg[k], r - l + 1);
		if (k < seg.size() / 2) {
			lazy[2 * k] = mm(lazy[k], lazy[2 * k]);
			lazy[2 * k + 1] = mm(lazy[k], lazy[2 * k + 1]);
		}
		lazy[k] = Me;
	}
	void apply(int a, int b, M m, int k, int l, int r) {
		eval(k, l, r);
		if (r < a || b < l)return;
		if (a <= l && r <= b) {
			lazy[k] = mm(m, lazy[k]);
			eval(k, l, r);
		}
		else {
			apply(a, b, m, 2 * k, l, (l + r) / 2);
			apply(a, b, m, 2 * k + 1, (l + r) / 2 + 1, r);
			seg[k] = tt(seg[2 * k], seg[2 * k + 1]);
		}
	}
	void apply(int a, int b, M m) {
		apply(a, b, m, 1, 0, seg.size() / 2 - 1);
	}
	T get(int a, int b, int k, int l, int r) {
		if (r < a || b < l)return Te;
		eval(k, l, r);
		if (a <= l && r <= b)return seg[k];
		else return tt(get(a, b, 2 * k, l, (l + r) / 2), get(a, b, 2 * k + 1, (l + r) / 2 + 1, r));
	}
	T get(int a, int b) {
		return get(a, b, 1, 0, seg.size() / 2 - 1);
	}
	void set(int n, T t) {
		int RN = seg.size() / 2;
		int l = 0, r = RN - 1;
		for (int t = snum; t > 0; t--) {
			eval((n + RN) >> t, l, r);
			if (((n + RN) >> (t - 1)) & 1) {
				l = ((l + r) >> 1) + 1;
			}
			else {
				r = (l + r) >> 1;
			}
		}
		eval((n + RN), n, n);
		seg[n + RN] = t;
		l = n;
		r = n;
		n += RN;
		while ((n >> 1) > 0) {
			if (n & 1) {
				l = 2 * l - r - 1;
			}
			else {
				r = 2 * r - l + 1;
			}
			n >>= 1;
			eval(n * 2, l, (l + r) >> 1);
			eval(n * 2 + 1, ((l + r) >> 1) + 1, r);
			seg[n] = tt(seg[2 * n], seg[2 * n + 1]);
		}
	}
};

LL modpow(LL base, int p) {
	if (p == 0)return 1;
	LL ans = modpow(base, p >> 1);
	ans = (ans * ans) % mod;
	if (p & 1) {
		ans = (ans * base) % mod;
	}
	return ans;
}

void solve() {
	LL ninerev = modpow(9, mod - 2);
	vector<PLL> initial(N, PLL(1, 1));
	VLL tle(2e5 + 1, 1);   //10^n
	for (int n=1;n<=2e5;n++){
		tle[n] = (tle[n - 1] * 10) % mod;
	}
	LazySegtree<PLL, LL> seg(
		initial,
		[&](PLL a, PLL b) {
		if (a.second == 0)return b;
		if (b.second == 0)return a;
		LL first = (a.first * tle[b.second] + b.first) % mod;
		LL second = a.second + b.second;
		return PLL(first, second);
	}, [&](LL m, PLL t, int n) {
		if (t.second == 0)return t;
		if (m == -1)return t;
		LL res = (tle[n] - 1) % mod;
		if (res < 0)res += mod;
		res = (res * ninerev) % mod;
		res = (res * m) % mod;
		return PLL(res,n);
	}, [&](LL m2, LL m1) {
		if (m2 == -1)return m1;
		return m2;
	}, PLL(1, 0), (LL)(-1)
		);
	for (int q = 0; q < Q; q++) {
		seg.apply(L[q] - 1, R[q] - 1, D[q]);
		cout << seg.get(0, N - 1).first << "\n";
	}
}

void naive() {
}

void outputinput() {
}

Measured memory_bytes: 24548