#include "bits/stdc++.h"

using namespace std;

#define _ ios_base::sync_with_stdio(0);cin.tie(0);
#define endl '\n'
#define debug(x) cerr << #x << " == " << (x) << '\n';
#define all(X) (X).begin(), (X).end()
#define sz(X) (int)X.size()

using ll = long long;

const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3fLL;

const ll MOD = 998244353LL;

ll power(ll x, int p)
{
    ll res = 1;
    while (p)
    {
        if (p & 1) res = (res * x) % MOD;
        p >>= 1;
        x = (x * x) % MOD;
    }
    return res;
}

const int NMAX = 2e5;
ll ones[NMAX + 1];

struct Number
{
    ll val = 0;
    int len = 0;
    Number(ll val, int len) : val(val), len(len) {}

    Number operator+(const Number& rhs) const
    {
        ll newval = (rhs.val + power(10, rhs.len) * val % MOD) % MOD;
        int newlen = len + rhs.len;
        return Number(newval, newlen);
    }
};

template<typename X, typename T=X>
struct F1
{
    X add;
    explicit F1(X add) : add(add) {}
    void apply(T& old, int L, int R) const
    {
        if (add != -1)
            old = Number(add * ones[R - L + 1] % MOD, R - L + 1);
    }
    void compose(const F1& op, int L, int R)
    {
        if (op.add != -1) add = op.add;
    }
};

template<typename T, typename F>
class SegmentTree
{
private:
    const int n; const T Tid; const F Fid;
    vector<T> st; vector<F> lazy;
    int left(int p) const { return 2 * p + 1; }
    int right(int p) const { return 2 * p + 2; }
    T combine(const T& resl, const T& resr)
    {
        return resl + resr;
    }
    void push(int p, int l, int r)
    {
        lazy[p].apply(st[p], l, r);
        if (l != r)
        {
            int m = l + (r - l) / 2;
            lazy[left(p)].compose(lazy[p], l, m);
            lazy[right(p)].compose(lazy[p], m + 1, r);
        }
        lazy[p] = Fid;
    }
    void update(int p, int l, int r, int ql, int qr, F op)
    {
        if (r < ql || qr < l) push(p, l, r);
        else if (ql <= l && r <= qr) { lazy[p].compose(op, l, r); push(p, l, r); }
        else
        {
            int m = l + (r - l) / 2;
            push(p, l, r);
            update(left(p), l, m, ql, qr, op);
            update(right(p), m + 1, r, ql, qr, op);
            st[p] = combine(st[left(p)], st[right(p)]);
        }
    }
    T query(int p, int l, int r, int ql, int qr)
    {
        if (r < ql || qr < l) return Tid;
        push(p, l, r);
        if (ql <= l && r <= qr) return st[p];
        int m = l + (r - l) / 2;
        T resl = query(left(p), l, m, ql, qr);
        T resr = query(right(p), m + 1, r, ql, qr);
        return combine(resl, resr);
    }
public:
    SegmentTree(const vector<T>& a, T Tid, F Fid) : n(sz(a)), Tid(Tid), Fid(Fid)
    {
        st.assign(4 * n + 1, Tid);
        lazy.assign(4 * n + 1, Fid);
        function<void(int, int, int)> build = [&](int p, int l, int r)
        {
            if (l == r) st[p] = a[l];
            else
            {
                int m = l + (r - l) / 2;
                build(left(p), l, m), build(right(p), m + 1, r);
                st[p] = combine(st[left(p)], st[right(p)]);
            }
        };
        build(0, 0, n - 1);
    }
    void update(int l, int r, F op) { update(0, 0, n - 1, l, r, op); }
    T query(int l, int r) { return query(0, 0, n - 1, l, r); }
};

int main()
{ _
    ones[1] = 1LL;
    for (int x = 2; x <= NMAX; ++x)
        ones[x] = (10 * ones[x - 1] + 1) % MOD;

    int n, q; cin >> n >> q;
    vector<Number> a(n, Number(1, 1));

    using F = F1<int, Number>;
    SegmentTree st(a, Number(0, 0), F(-1));

    for (int z = 0; z < q; ++z)
    {
        int l, r, d; cin >> l >> r >> d; --l, --r;
        st.update(l, r, F(d));
        ll ans = st.query(0, n - 1).val;
        cout << ans << endl;
    }

    exit(0);
}



Measured memory_bytes: 23984