#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void Yes() {cout << "Yes\n";}
void No() {cout << "No\n";}
void YES() {cout << "YES\n";}
void NO() {cout << "NO\n";}
constexpr int P = 998244353;
/*
	note			: The function modinv(a, P) doesn't work when a and P are not coprime.
	last verified	: 2020/09/21, AtCoder
		problem			: https://atcoder.jp/contests/practice2/tasks/practice2_k
		submission		: https://atcoder.jp/contests/practice2/submissions/16935191
*/
#include <iostream>
#include <vector>
template<long long P> long long modinv(long long n) {
	long long a = P, u = 1, v = 0;
	while (a) {
		long long t = n / a;
		n -= t * a; std::swap(n, a);
		u -= t * v; std::swap(u, v);
	}
	u %= P;
	if (u < 0) u += P;
	return u;
}

template<long long MOD> struct modint {
	long long value;
	modint(const long long& n = 0) : value(n) {
		value %= MOD;
		if (value < 0) value += MOD;
	}
	inline bool operator==(const modint<MOD>& right)const{return (value == right.value);}
	inline bool operator!=(const modint<MOD>& right)const{return (value != right.value);}
	inline bool operator<(const modint<MOD>& right)const{return (value < right.value);}
	inline bool operator>(const modint<MOD>& right)const{return (value > right.value);}
	inline bool operator<=(const modint<MOD>& right)const{return (value <= right.value);}
	inline bool operator>=(const modint<MOD>& right)const{return (value >= right.value);}
	modint<MOD> operator+(const modint<MOD>& right)const{modint<MOD> ret = value + right.value; return ret;}
	modint<MOD> operator-(const modint<MOD>& right)const{modint<MOD> ret = value - right.value; return ret;}
	modint<MOD> operator*(const modint<MOD>& right)const{modint<MOD> ret = value * right.value; return ret;}
	modint<MOD> operator/(const modint<MOD>& right)const{modint<MOD> ret = value * modinv<MOD>(right.value); return ret;}
	inline modint<MOD>& operator+=(modint<MOD>& right) {return *this = *this + right;}
	inline modint<MOD>& operator-=(modint<MOD>& right) {return *this = *this - right;}
	inline modint<MOD>& operator*=(modint<MOD>& right) {return *this = *this * right;}
	inline modint<MOD>& operator/=(modint<MOD>& right) {return *this = *this / right;}
	inline modint<MOD> operator-()const{return (*this) * -1;}
	inline modint<MOD>& operator++() {return (*this) += 1;}
	inline modint<MOD>& operator++(int) {return ++(*this) - 1;}
	inline modint<MOD>& operator--() {return (*this) -= 1;}
	inline modint<MOD>& operator--(int) {return --(*this) + 1;}
};
template<long long MOD> inline modint<MOD> operator+(const long long& left, const modint<MOD>& right) {
	return right + left;
}
template<long long MOD> inline modint<MOD> operator-(const long long& left, const modint<MOD>& right) {
	return right * -1 + left;
}
template<long long MOD> inline modint<MOD> operator*(const long long& left, const modint<MOD>& right) {
	return right * left;
}
template<long long P> inline modint<P> operator/(const long long& left, const modint<P>& right) {
	return modinv<P>(right.value) * (left % P);
}

template<long long MOD> modint<MOD> modpow(const modint<MOD>& a, const long long& n) {
	if (n == 0) return 1;
	if (a == 0) return 0;
	modint<MOD> ret = a;
	long long cnt = 1;
	while (cnt * 2 <= n) {
		ret *= ret;
		cnt *= 2;
	}
	return ret * modpow<MOD>(a, n - cnt);
}

std::vector<long long> factorial;
std::vector<long long> factorial_inv;

template<long long P> void make_table(const int& n) {
	factorial.resize(n + 1, 1);
	factorial_inv.resize(n + 1, 1);
	for (int i = 1; i <= n; i++) factorial[i] = factorial[i - 1] * i % P;
	factorial_inv[n] = modinv<P>(factorial[n]);
	for (int i = n - 1; i >= 0; i--) factorial_inv[i] = factorial_inv[i + 1] * (i + 1) % P;
}

template<long long P> modint<P> permutation(const int& n, const int& r) {
	if (n <= factorial.size()) return factorial[n] * factorial_inv[n - r];
	std::cerr << "attention : factorial table is not constructed" << std::endl;
	r = std::min(r, n - r);
	modint<P> ret = 1;
	for (int i = 0; i < r; i++) ret *= n - i;
	return ret;
}

template<long long P> modint<P> combination(const int& n, const int& r) {
	if (n <= factorial.size()) return permutation<P>(n, r) * factorial_inv[r];
	std::cerr << "attention : factorial table is not constructed" << std::endl;
	r = std::min(r, n - r);
	modint<P> ret = 1;
	for (int i = 0; i < r; i++) {
		ret *= n - i;
		ret /= i + 1;
	}
	return ret;
}

template<long long MOD> std::istream& operator>>(std::istream& is, modint<MOD>& target) {
	is >> target.value;
	target.value %= MOD;
	if (target.value < 0) target.value += MOD;
	return is;
}
template<long long MOD> inline std::ostream& operator<<(std::ostream& os, const modint<MOD>& target) {
	os << target.value;
	return os;
}

vector<modint<P>> v;

template<typename T, typename E, typename F, typename G, typename H> struct lazy_segment_tree {
private :
	int N; // the number of leaves
	std::vector<T> V;
	std::vector<E> W;
	const F op_V;
	const G op_W;
	const H op_V_from_W;
	const T id_V;
	const E id_W;
	void lazy_evaluation(const int& i, const int& l, int r) {
		int w = r - l;
		V[i] = op_V_from_W(V[i], W[i], l, r);
		if (w > 1) {
			W[i * 2] = op_W(W[i * 2], W[i]);
			W[i * 2 + 1] = op_W(W[i * 2 + 1], W[i]);
		}
		W[i] = id_W;
	}
public :
	lazy_segment_tree(const std::vector<T>& v, const F& f, const G& g, const H& h, const T& t, const E& e)
	: op_V(f), op_W(g), op_V_from_W(h), id_V(t), id_W(e) {
		int n = 1, sz = v.size();
		while (n < sz) n *= 2;
		N = n;
		V.resize(N * 2, id_V);
		W.resize(N * 2, id_W);
		for (int i = 0; i < sz; i++) V[N + i] = v[i];
		for (int i = N - 1; i > 0; i--) V[i] = op_V(V[i * 2], V[i * 2 + 1]);
	}
	lazy_segment_tree(const int& sz, const F& f, const G& g, const H& h, const T& t, const E& e)
	: op_V(f), op_W(g), op_V_from_W(h), id_V(t), id_W(e) {
		int n = 1;
		while (n < sz) n *= 2;
		N = n;
		V.resize(N * 2, id_V);
		W.resize(N * 2, id_W);
	}
	void range_update(const int& L, const int& R, const E& e, const int& i = 1, const int& l = 0, int r = -1) {
		if (L == R) return;
		if (r == -1) r = N;
		if (L <= l && r <= R) {
			W[i] = op_W(W[i], e);
			lazy_evaluation(i, l, r);
		} else {
			if (W[i] != id_W) lazy_evaluation(i, l, r);
			int mid = (l + r) / 2;
			if (L < mid) range_update(L, R, e, i * 2, l, mid);
			else if (W[i * 2] != id_W) lazy_evaluation(i * 2, l, mid);
			if (mid < R) range_update(L, R, e, i * 2 + 1, mid, r);
			else if (W[i * 2 + 1] != id_W) lazy_evaluation(i * 2 + 1, mid, r);
			V[i] = op_V(V[i * 2], V[i * 2 + 1]);
		}
	}
	T range_fold(const int& L, const int& R, const int& i = 1, const int& l = 0, int r = -1) {
		if (r == -1) r = N;
		if (W[i] != id_W) lazy_evaluation(i, l, r);
		if (L <= l && r <= R) return V[i];
		T ret = id_V;
		int mid = (l + r) / 2;
		if (L < mid) ret = op_V(ret, range_fold(L, R, i * 2, l, mid));
		if (mid < R) ret = op_V(ret, range_fold(L, R, i * 2 + 1, mid, r));
		return ret;
	}
	T operator[](const int& i) {return range_fold(i, i + 1);}
};

int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);

 	int n, q;
	cin >> n >> q;

	vector<modint<P>> a(n, 1);
	modint<P> x = 10, y = 10;
	for (int i = n - 2; i >= 0; i--) {
		a[i] *= x;
		x *= y;
	}

	v.resize(n + 1, 1);
	v[n] = 0;
	for (int i = n - 2; i >= 0; i--) v[i] = v[i + 1] * 10;
	for (int i = n - 1; i >= 0; i--) v[i] += v[i + 1];

	auto f = [] (modint<P> a, modint<P> b) {return a + b;};
	auto g = [] (modint<P> a, modint<P> b) {return b;};
	auto h = [&] (modint<P> a, modint<P> b, int l, int r) {
		return b * (v[l] - v[r]);
	};
	modint<P> id = 0;
	lazy_segment_tree<modint<P>, modint<P>, decltype(f), decltype(g), decltype(h)> st(a, f, g, h, id, id);

	while (q--) {
		int l, r, d;
		cin >> l >> r >> d;
		st.range_update(l - 1, r, d);
		cout << st.range_fold(0, n) << endl;
	}
}

Measured memory_bytes: 14564