#include <map>
#include <set>
#include <list>
#include <cmath>
#include <deque>
#include <stack>
#include <queue>
#include <array>
#include <bitset>
#include <cstdio>
#include <string>
#include <vector>
#include <random>
#include <chrono>
#include <utility>
#include <numeric>
#include <cstdlib>
#include <cstring>
#include <climits>
#include <sstream>
#include <assert.h>
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <functional>
#include <unordered_map>

using namespace std;
struct _ { ios_base::Init i; _() { ios_base::sync_with_stdio(false), cin.tie(NULL), cout.tie(NULL); } } _;

const int maxn = 2e5;
const int MOD = 998244353;

class Modint {
public:
	long long val;

	Modint (long long _val = 0)
		: val((_val + MOD) % MOD) {}

	Modint operator+ (Modint other) {
		return Modint(val + other.val);
	}

	void operator+= (Modint other) {
		val += other.val;
		val %= MOD;
	}

	Modint operator- () {
		return Modint(MOD - val);
	}

	Modint operator- (Modint other) {
		return Modint(val + MOD - other.val);
	}

	void operator-= (Modint other) {
		val += MOD - other.val;
		val %= MOD;
	}

	Modint operator* (Modint other) {
		return Modint(val * other.val);
	}

	void operator*= (Modint other) {
		val *= other.val;
		val %= MOD;
	}

	bool operator== (Modint other) {
		return val == other.val;
	}

	bool operator!= (Modint other) {
		return val != other.val;
	}
};

Modint exp (Modint a, int k) {
	if (k == 0) {
		return Modint(1);
	} else if (k % 2 == 0) {
		Modint half = exp(a, k / 2);
		return half * half;
	} else {
		return a * exp(a, k - 1);
	}
}

Modint inv (Modint a) {
	return exp(a, MOD - 2);
}

ostream& operator<< (ostream& out, Modint p) {
	out << p.val;
	return out;
}

// vector<int> a(maxn, 0);
int n, q;
Modint INV9 = inv(9);
vector<Modint> pw(maxn + 1, 1);
vector<Modint> tree(4 * maxn + 1, 0); //update->[l,r]+=inc, query->sum([l,r])
vector<int> lazy(4 * maxn + 1, 0);

// #ifdef HOME
// void print(int sze) {
// 	cerr << "-------------------------------------------------------------------------------------------------\n";
// 	cerr << "{ind, tree[ind], lazy[ind]}\n";

// 	for (int i = 1; i <= sze; i++) {
// 		cerr << "{" << i << ", " << tree[i] << ", " << lazy[i] << "} ";
// 		if (__builtin_popcount(i + 1) == 1) cerr << endl;
// 	}
// 	cerr << "\n-------------------------------------------------------------------------------------------------\n";
// }
// #else
// void print(int sze) {}
// #endif

void merge(int l, int r, int ind) {
	int mid((l + r) >> 1);
	int l1 = l, r1 = mid, l2 = mid + 1, r2 = r;
	int x = r2 - l2 + 1;
	Modint left = tree[2 * ind], right = tree[2 * ind + 1];

	tree[ind] = pw[x] * left + right;
	return;
}

void push(int l, int r, int ind) {
	if (lazy[ind] != 0) {
		int x = r - l + 1;
		tree[ind] = (pw[x] - 1) * INV9 * lazy[ind];

		if (l != r) {
			lazy[2 * ind] = lazy[ind];
			lazy[2 * ind + 1] = lazy[ind];
		}
		lazy[ind] = 0;
	}
}

void build(int l, int r, int ind) {
	if (l == r) {
		tree[ind] = 1;
		return;
	}

	int mid((l + r) >> 1);
	build(l, mid, 2 * ind);
	build(mid + 1, r, 2 * ind + 1);
	merge(l, r, ind);
}

void update(int ul, int ur, int uv, int l, int r, int ind) {
	push(l, r, ind);

	if (ur < l or r < ul) return;

	if (ul <= l and r <= ur) {
		lazy[ind] = uv;
		push(l, r, ind);
		return;
	}

	int mid((l + r) >> 1);
	update(ul, ur, uv, l, mid, 2 * ind);
	update(ul, ur, uv, mid + 1, r, 2 * ind + 1);
	merge(l, r, ind);
}

int main() {

	for (int i = 1; i <= maxn; i++) pw[i] = pw[i - 1] * 10;

	cin >> n >> q;

	build(1, n, 1);

	while (q--) {
		int l, r, d; cin >> l >> r >> d;
		update(l, r, d, 1, n, 1);

		cout << tree[1] << "\n";
	}

	return 0;
}

Measured memory_bytes: 14216