#include <cmath>
#include <vector>
#include <iostream>
#include <algorithm>
#include <set>
#include <iomanip>
#include <queue>
#include <string>
#include <map>
#include <fstream>
#include <cassert>
#include <stack>
#include <climits>
#include <array>
#include <unordered_set>
#include <unordered_map>
#include <memory>
#include <functional>
#include <cfloat>
#include <numeric>

#include <atcoder/segtree>

constexpr long long int MOD = 998244353;

class SegTree {
	std::vector<std::vector<long long int>> all_apply, cache, multiplier;
	void update(const int pos) {
		update(0, pos);
	}
	void apply(const int pos) {
		apply(0, pos);
	}
	void update(const int depth, const int pos) {
		if (!is_valid(depth, pos)) return;
		cache[depth][pos] = (get(depth - 1, pos << 1) + get(depth - 1, (pos << 1) + 1)) % MOD;
		update(depth + 1, pos >> 1);
	}
	void apply(const int depth, const int pos) {
		if (!is_valid(depth, pos)) return;
		apply(depth + 1, pos >> 1);
		if (all_apply[depth][pos] == -1) return;
		set_apply(depth - 1, pos << 1, all_apply[depth][pos]);
		set_apply(depth - 1, (pos << 1) + 1, all_apply[depth][pos]);
		all_apply[depth][pos] = -1;
		cache[depth][pos] = (get(depth - 1, pos << 1) + get(depth - 1, (pos << 1) + 1)) % MOD;
	}
	void set_apply(const int depth, const int pos, const int value) {
		if (!is_valid(depth, pos)) return;
		all_apply[depth][pos] = value;
	}
	long long int get(const int depth, const int pos) {
		if (!is_valid(depth, pos)) return 0;
		if (all_apply[depth][pos] == -1) return cache[depth][pos];
		return all_apply[depth][pos] * multiplier[depth][pos] % MOD;
	}
	bool is_valid(const int depth, const int pos) {
		if (depth < 0 || all_apply.size() <= depth) return false;
		if (all_apply[depth].size() <= pos) return false;
		return true;
	}
public:
	SegTree(int size) : all_apply{ std::vector<long long int>(size, 1) }, cache{ std::vector<long long int>(size) }, multiplier{ std::vector<long long int>(size, 1) }{
		while (all_apply.back().size() > 1) {
			all_apply.emplace_back(all_apply.back().size() >> 1, 1);
			cache.emplace_back(cache.back().size() >> 1);
			multiplier.emplace_back(multiplier.back().size() >> 1);
		}
		for (auto i = 2; i <= size; ++i) {
			multiplier[0][size - i] = 10 * multiplier[0][size - i + 1] % MOD;
		}
		for (auto i = 1; i < multiplier.size(); ++i) {
			for (auto j = 0; j < multiplier[i].size(); ++j) {
				multiplier[i][j] = (multiplier[i - 1][j << 1] + multiplier[i - 1][(j << 1) + 1]) % MOD;
			}
		}
	}
	void change(int from, int to, int new_digit) {
		apply(from); apply(to);
		int l{ from }, r{ to };
		for (auto i = 0; i < all_apply.size(); ++i) {
			if (l & 1) {
				all_apply[i][l++] = new_digit;
			}
			if ((r & 1) == 0) {
				all_apply[i][r--] = new_digit;
			}
			if (l > r) break;
			l >>= 1;
			r >>= 1;
		}
		update(from); update(to);
	}
	long long int all() {
		long long int result{ 0 };
		int pos = all_apply[0].size() - 1;
		for (auto i = 0; i < all_apply.size(); ++i) {
			if ((pos & 1) == 0) {
				result = (result + get(i, pos--)) % MOD;
			}
			if (pos < 0) break;
			pos >>= 1;
		}
		return result;
	}
};

int main() {
	int n, q; std::cin >> n >> q;
	SegTree seg(n);
	for (auto i = 0; i < q; ++i) {
		int left, right, digit; std::cin >> left >> right >> digit;
		--left; --right;
		seg.change(left, right, digit);
		std::cout << seg.all() << '\n';
	}
}

Measured memory_bytes: 12576