#include <iostream>
#include <vector>
#include <algorithm>
using i64 = long long;

template <typename T, typename U, typename F, typename G, typename H>
class LazySegmentTree {
    int size;
    T tid;
    std::vector<T> dat;
    U uid;
    std::vector<U> lazy;

    F f;
    G g;
    H h;

    void propagate(const int k, const int l, const int r) {
        if (lazy[k] == uid) return;

        if (k < size - 1) {
            lazy[2 * k + 1] = h(lazy[2 * k + 1], lazy[k]);
            lazy[2 * k + 2] = h(lazy[2 * k + 2], lazy[k]);
        }

        dat[k] = g(dat[k], lazy[k], r - l);
        lazy[k] = uid;
    }

    T update_impl(const int a, const int b, const U x, const int k, const int l, const int r) {
        propagate(k, l, r);
        if (r <= a || b <= l) return dat[k];
        if (a <= l && r <= b) {
            lazy[k] = h(lazy[k], x);
            propagate(k, l, r);
            return dat[k];
        }

        return dat[k] = f(update_impl(a, b, x, 2 * k + 1, l, (l + r) / 2),
                          update_impl(a, b, x, 2 * k + 2, (l + r) / 2, r));
    }

    T query_impl(const int a, const int b, const int k, const int l, const int r) {
        propagate(k, l, r);
        if (r <= a || b <= l) return tid;
        if (a <= l && r <= b) return dat[k];
        return f(query_impl(a, b, 2 * k + 1, l, (l + r) / 2),
                 query_impl(a, b, 2 * k + 2, (l + r) / 2, r));
    }

    static int calc_size(const int n) {
        int ret = 2;
        while (ret < n) ret *= 2;
        return ret;
    }

public:
    LazySegmentTree(const int n, const T &tid, const U &uid, F f, G g, H h)
        : size(calc_size(n))
        , tid(tid)
        , dat(size * 2 - 1, tid)
        , uid(uid)
        , lazy(size * 2 - 1, uid)
        , f(f)
        , g(g)
        , h(h) {}

    template <template <class> class Container, class TId>
    LazySegmentTree(const Container<T> &v, const TId &tid, const U &uid, F f, G g, H h)
        : size(calc_size(v.size()))
        , tid(tid)
        , dat(size * 2 - 1, tid)
        , uid(uid)
        , lazy(size * 2 - 1, uid)
        , f(f)
        , g(g)
        , h(h)
    {
        std::copy(v.begin(), v.end(), dat.begin() + size - 1);
        dig(0);
    }

    void dig(const int v) {
        if (v >= size - 1) return;
        dig(2 * v + 1);
        dig(2 * v + 2);
        dat[v] = f(dat[2 * v + 1], dat[2 * v + 2]);
    }

    void update(const int a, const int b, const U x) {
        update_impl(a, b, x, 0, 0, size);
    }

    T query(const int a, const int b) {
        return query_impl(a, b, 0, 0, size);
    }

    T operator[](const int i) {
        return query(i, i + 1);
    }
};

constexpr auto pow(long long x, long long n, const long long mod) {
    long long ret = 1;
    while(n > 0) {
        if ((n & 1) == 1) ret = (ret * x) % mod;
        x = (x * x) % mod;
        n >>= 1;
    }
    return ret;
}

constexpr auto inverse(const long long x, const long long p) {
    return pow(x, p - 2, p);
}

int main() {
    constexpr i64 mod = 998244353;
    int n, q;
    std::cin >> n >> q;

    std::vector<i64> p10 { 1 };
    for (int i = 0; i < 200010; i++) p10.push_back(p10.back() * 10 % mod);
    constexpr i64 i9 = inverse(9, mod);

    std::vector v(n, std::pair { 1ll, 1 });
    LazySegmentTree lst(v, std::pair { 0ll, 0 }, 0,
        [&,mod](const auto &lhs, const auto &rhs) {
            return std::make_pair(
                (lhs.first * p10[rhs.second] % mod + rhs.first) % mod,
                lhs.second + rhs.second
            );
        },
        [&,mod,i9](const auto, const auto u, const auto len) {
            const i64 r = (p10[len] + mod - 1) % mod * i9 % mod * u % mod;
            return std::make_pair(r, len);
        },
        [](const auto, const auto curr) { return curr; });

    while (q--) {
        int l, r, d;
        std::cin >> l >> r >> d;
        lst.update(l - 1, r, d);
        std::cout << lst.query(0, n).first << '\n';
    }

    return 0;
}


Measured memory_bytes: 18236