//#include "bits/stdc++.h"

#define _USE_MATH_DEFINES

#include <iostream>
#include <sstream>
#include <iomanip>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <numeric>
#include <functional>
#include <utility>
#include <tuple>
#include <vector>
#include <string>
#include <list>
#include <set>
#include <unordered_set>
#include <map>
#include <unordered_map>
#include <queue>
#include <deque>
#include <stack>
#include <iterator>
#include <bitset>
#include <complex>
#include <limits>
#include <random>
#include<fstream>
#include<array>


using namespace std;

#define rep(i,a,b) for(int i=(a), i##_len=(b);i<i##_len;i++)
#define rrep(i,a,b) for(int i=(b)-1;i>=(a);i--)
#define all(c) begin(c),end(c)

#define int ll
#define SZ(x) ((int)(x).size())
#define pb push_back
#define mp make_pair

typedef unsigned long long ull;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<ll, int> pli;
typedef pair<double, double> pdd;
typedef vector< vector<int> > mat;

template<class T> bool chmax(T &a, const T &b) { if (a < b) { a = b; return true; } return false; }
template<class T> bool chmin(T &a, const T &b) { if (b < a) { a = b; return true; } return false; }

const int INF = sizeof(int) == sizeof(long long) ? 0x3f3f3f3f3f3f3f3fLL : 0x3f3f3f3f;
const int MOD = 998244353;

const double EPS = 1e-9;

template <typename T, typename E>
struct LazySegmentTree {
	typedef function<T(T, T)> F;//merge
	typedef function<T(T, E)> G;//dat lazy
	typedef function<E(E, E)> H;//lazy lazy
	typedef function<E(E, int)> P;//lazy len

	vector<T> dat; vector<E> laz;
	int n; F f; G g; H h; P p;
	T d1;//datの単位元
	E d0;//lazyの単位元

	LazySegmentTree(int m, F f, G g, H h, P p, T d1, E d0) : f(f), g(g), h(h), p(p), d1(d1), d0(d0)
	{
		n = 1;
		while (n < m) n *= 2;
		dat.assign(2 * n - 1, d1);
		laz.assign(2 * n - 1, d0);
	}

	void init(const vector<T> v)
	{
		for (int i = 0; i < SZ(v); i++) dat[i + n - 1] = v[i];
		for (int i = n - 2; i >= 0; i--) dat[i] = f(dat[i * 2 + 1], dat[i * 2 + 2]);
	}

	inline void eval(int len, int k)
	{
		if (laz[k] == d0) return;
		if (k * 2 + 1 < n * 2 - 1)
		{
			laz[k * 2 + 1] = h(laz[k * 2 + 1], laz[k]);
			laz[k * 2 + 2] = h(laz[k * 2 + 2], laz[k]);
		}
		dat[k] = g(dat[k], p(laz[k], len));
		laz[k] = d0;
	}

	void update(int a, int b, E x, int k, int l, int r)
	{
		eval(r - l, k);
		if (a <= l && r <= b)
		{
			laz[k] = h(laz[k], x);
			eval(r - l, k);
		}
		else if (a < r&&l < b)
		{
			update(a, b, x, k * 2 + 1, l, (l + r) / 2);
			update(a, b, x, k * 2 + 2, (l + r) / 2, r);

			dat[k] = f(dat[k * 2 + 1], dat[k * 2 + 2]);
		}
	}

	T query(int a, int b, int k, int l, int r)
	{
		eval(r - l, k);
		if (r <= a || b <= l) return d1;
		if (a <= l && r <= b) return dat[k];
		T vl = query(a, b, k * 2 + 1, l, (l + r) / 2);
		T vr = query(a, b, k * 2 + 2, (l + r) / 2, r);
		return f(vl, vr);
	}

	void update(int a, int b, E x) { update(a, b, x, 0, 0, n); }
	T query(int a, int b) { return query(a, b, 0, 0, n); }
	T operator[](const int &k) const { return dat[k + n - 1]; }
};

signed main()
{
	cin.tie(0);
	ios::sync_with_stdio(false);

	int N, Q;
	cin >> N >> Q;

	vector<int> TEN(200010), ELE(200010);
	TEN[0] = 1;
	ELE[0] = 1;
	rep(i, 1, 200010)
	{
		TEN[i] = (TEN[i - 1] * 10) % MOD;
		ELE[i] = (ELE[i-1] * 10 + 1) % MOD;
	}

	auto f = [&](pii a, pii b) {return mp((((a.first*TEN[b.second]) % MOD) + b.first) % MOD, a.second + b.second); };
	auto g = [&](pii a, pii b) {return b; };
	auto h = [&](pii a, pii b) {return b; };
	auto p = [&](pii a, int b) {return mp(a.first*ELE[b-1], b); };

	LazySegmentTree<pii, pii> st(N, f, g, h, p, mp(0LL, 0LL), mp(INF, INF));
	st.init(vector<pii>(N, mp(1, 1)));

	int l, r, d;
	rep(i, 0, Q)
	{
		cin >> l >> r >> d;

		st.update(l - 1, r, mp(d, 0));
		cout << st.query(0, N).first << endl;
	}

	return 0;
}


Measured memory_bytes: 25916