#include <bits/stdc++.h>
using namespace std;using ll=int_fast64_t;using ld=long double;constexpr ll INF=1LL<<60,MOD=998244353;
void solve();int main(){cin.tie(nullptr);ios::sync_with_stdio(false);cout<<fixed<<setprecision(10);solve();return 0;}
#define SELECTOR(_1,_2,_3,_4,SELECT,...) SELECT
#define rep(...) SELECTOR(__VA_ARGS__,_rep2,_rep1,_rep0)(__VA_ARGS__)
#define _rep0(i,n) for(int i=0;i<(int)n;++i)
#define _rep1(i,k,n) for(int i=k;i<(int)n;++i)
#define _rep2(i,k,n,d) for(int i=k;d>0?i<(int)n:i>(int)n;i+=d)
#ifdef __LOCAL
#include "ostreams.h"
#endif
template<class T> inline bool chmax(T &a,const T &b){if(a<b){a=b;return 1;}return 0;}
template<class T> inline bool chmin(T &a,const T &b){if(a>b){a=b;return 1;}return 0;}
template<class T> vector<T> make_vector(size_t a,T b){return vector<T>(a,b);}
template<class... Ts> auto make_vector(size_t a,Ts... ts){return vector<decltype(make_vector(ts...))>(a,make_vector(ts...));}
void print(){cerr<<endl;} template<class T,class... Ts> void print(const T& a,const Ts&... ts){cerr<<a<<' ';print(ts...);}


template<ll MOD>
class Modint{
private:
    ll x;
public:
    constexpr Modint(ll v = 0) : x(v % MOD + (v >= 0 ? 0 : MOD)) {}
    constexpr Modint operator+(const Modint &rhs) const {return Modint(*this) += rhs;}
    constexpr Modint operator-(const Modint &rhs) const {return Modint(*this) -= rhs;}
    constexpr Modint operator*(const Modint &rhs) const {return Modint(*this) *= rhs;}
    constexpr Modint operator/(const Modint &rhs) const {return Modint(*this) /= rhs;}
    constexpr Modint operator+=(const Modint &rhs) {x += rhs.x; if(x >= MOD) x -= MOD; return *this;}
    constexpr Modint operator-=(const Modint &rhs) {x -= rhs.x; if(x < 0) x += MOD; return *this;}
    constexpr Modint operator*=(const Modint &rhs) {(x *= rhs.x) %= MOD; return *this;}
    constexpr Modint operator/=(const Modint &rhs) {return *this *= pow(rhs, -1);}
    template<class T> constexpr explicit operator T() const {return x;}
    constexpr static Modint pow(Modint a, ll p){
        if(p < 0){
            ll b = MOD, u = 1, v = 0;
            while(b){ll t = a.x / b; a.x -= t * b; a.x += b; b = a.x - b; a.x -= b; u -= t * v; u += v; v = u - v; u -= v;}
            a = u; p *= -1;}
        Modint res = 1;
        while(p){if(p & 1) res *= a; a *= a; p >>= 1;}
        return res;
    }
    constexpr void from_stream(istream &st) {st >> x;}
    constexpr void to_stream(ostream &st) const {st << x;}
};
template<ll MOD, class T> constexpr Modint<MOD> operator+(T a, Modint<MOD> b){return (Modint<MOD>)a + b;}
template<ll MOD, class T> constexpr Modint<MOD> operator-(T a, Modint<MOD> b){return (Modint<MOD>)a - b;}
template<ll MOD, class T> constexpr Modint<MOD> operator*(T a, Modint<MOD> b){return (Modint<MOD>)a * b;}
template<ll MOD, class T> constexpr Modint<MOD> operator/(T a, Modint<MOD> b){return (Modint<MOD>)a / b;}
template<ll MOD> constexpr istream& operator>>(istream &st, Modint<MOD> &a){a.from_stream(st); return st;}
template<ll MOD> constexpr ostream& operator<<(ostream &st, const Modint<MOD> &a){a.to_stream(st); return st;}
using mint = Modint<MOD>;

template<class T, class E>
class LazySegmentTree{
    ll n = 1, logn = 0;
    function<T(T, T)> dot; T unit; function<E(E, E)> compose; E identity; function<T(E, T)> act; vector<T> tree; vector<E> lazy;
    constexpr void ascend(ll i){while(i >>= 1) tree[i] = act(lazy[i], dot(tree[i << 1], tree[i << 1 | 1]));}
    constexpr void descend(ll i){
        rep(k, logn, 0, -1){
            ll p = i >> k;
            E f = lazy[p];
            tree[p << 1] = act(f, tree[p << 1]); lazy[p << 1] = compose(f, lazy[p << 1]);
            tree[p << 1 | 1] = act(f, tree[p << 1 | 1]); lazy[p << 1 | 1] = compose(f, lazy[p << 1 | 1]);
            lazy[p] = identity;
        }
    }
public:
    constexpr LazySegmentTree(const vector<T> &A, function<T(T, T)> dot, T unit ,function<E(E, E)> compose, E identity ,function<T(E, T)> act) : dot(dot), unit(unit), compose(compose), identity(identity), act(act) {
        while(n < (ll)A.size()){n <<= 1; logn++;}
        tree.resize(2 * n, unit);
        lazy.resize(2 * n, identity);
        copy(A.begin(), A.end(), tree.begin() + n);
        rep(i, n - 1, 0, -1) tree[i] = dot(tree[i << 1], tree[i << 1 | 1]);
    }
    constexpr void range_act(ll l, ll r, E f){
        l += n; r += n;
        // propagation isn't necessary if monoid action is commutative
        descend(l); descend(r - 1);
        ll l0 = l, r0 = r;
        while(l < r){
            if(l & 1){tree[l] = act(f, tree[l]); lazy[l] = compose(f, lazy[l]); l++;}
            if(r & 1){r--; tree[r] = act(f, tree[r]); lazy[r] = compose(f, lazy[r]);}
            l >>= 1; r >>= 1;
        }
        ascend(l0); ascend(r0 - 1);
    }
    constexpr T sum(ll l, ll r){
        descend(l += n); descend((r += n) - 1);
        T l_val = unit, r_val = unit;
        while(l < r){
            if(l & 1) l_val = dot(l_val, tree[l++]);
            if(r & 1) r_val = dot(tree[--r], r_val);
            l >>= 1; r >>= 1;
        }
        return dot(l_val, r_val);
    }
};

using P = pair<mint, ll>;
void solve(){
    ll n, q; cin >> n >> q;
    auto dot = [](P a, P b){return P{a.first * mint::pow(10, b.second) + b.first, a.second + b.second};};
    P unit = {0, 0};
    auto compose = [](ll f, ll g){return f == 0 ? g : f;};
    ll identity = 0;
    auto act = [](ll f, P a){
        if(f == 0) return a;
        return P{f * (mint::pow(10, a.second) - 1) / 9, a.second};
    };

    LazySegmentTree<P, ll> tree(vector<P>(n, {1, 1}), dot, unit, compose, identity, act);
    
    rep(_, q){
        ll l, r, d; cin >> l >> r >> d;
        l--;
        tree.range_act(l, r, d);
        cout << tree.sum(0, n).first << '\n';
    }
}

Measured memory_bytes: 18764