//#undef DEBUG
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const ll llinf = (1ll<<61)-1;
const char lf = '\n', splf[] = " \n";
#define sz(a) int(a.size())
#define all(x) begin(x), end(x)
#define TCC template<class C
#define OSO ostream &operator<<(ostream &os, const
#ifdef DEBUG
const int DEBUG_END = 26;
#define DOS cout
#include <debug.h>
#else
#define bug(args...) void()
#define cbug(a, args...)
#endif
#define ASSERT(a, o, b, args...) if (!((a)o(b))) bug(a, b, ##args), assert((a)o(b));
#define fi first
#define se second
const int inf = 998244353,N=200005;
template<class C, class D> bool operator ==(const C &ls, const D &rs) { return !(ls<rs or rs<ls); }
template<class C, class D> bool operator !=(const C &ls, const D &rs) { return !(rs==ls); }
template<class C, class D> bool operator >(const C &ls, const D &rs) { return rs<ls; }
template<class C, class D> bool operator <=(const C &ls, const D &rs) { return !(rs<ls); }
template<class C, class D> bool operator >=(const C &ls, const D &rs) { return !(ls<rs); }
template<class C, class D> C& operator +=(C &x, const D &y) { return x = x+y; }
template<class C, class D> C& operator -=(C &x, const D &y) { return x = x-y; }
template<class C, class D> C& operator *=(C &x, const D &y) { return x = x*y; }
#include <ext/numeric>
using __gnu_cxx::power;
struct Int// Make sure to not do any operation with int outside [-inf, 2*inf), *1 to mod forcefully)
{
    int x;
    Int() = default;
    Int(const int &rs) : x(rs + (rs>=0 ? 0 : inf) - (rs<inf ? 0 : inf)) {};
    Int operator -() { return -x; }
    // Int operator ~() = delete;
    Int operator ~() { return power(*this, inf-2); }
    Int operator +(const Int &rs) const { return x+rs.x; }
    Int operator -(const Int &rs) const { return x-rs.x; }
    Int operator *(const Int &rs) const { return int(x*ll(rs.x)%inf); }
    Int operator <<(const int &rs) { return rs==1 ? *this+*this : *this*Int{1<<rs}; }
    Int& operator <<=(const int &rs) { return *this = *this<<rs; }
    Int& operator >>=(const int &rs) { return x>>=rs, *this; }  // only for power()
    Int& operator ++() { return *this += 1; }
    Int& operator --() { return *this -= 1; }
    Int operator ++(int) { Int ret = x; ++*this; return ret; }
    Int operator --(int) { Int ret = x; --*this; return ret; }
    friend istream& operator >>(istream &is, Int &rs) { return is>>rs.x; }
    friend ostream& operator <<(ostream &os, const Int &rs) { return os<<rs.x; }
    friend Int operator +(const Int &ls, const int &rs) { return ls+Int(rs); }
    friend Int operator +(const int &ls, const Int &rs) { return Int(ls)+rs; }
    friend Int operator -(const Int &ls, const int &rs) { return ls-Int(rs); }
    friend Int operator -(const int &ls, const Int &rs) { return Int(ls)-rs; }
    friend Int operator *(const Int &ls, const int &rs) { return ls*Int(rs); }
    friend Int operator *(const int &ls, const Int &rs) { return Int(ls)*rs; }
    bool operator <(const Int &rs) const { return x<rs.x; }
    friend bool operator <(const int &ls, const Int &rs) { return ls<rs.x; }
    friend bool operator <(const Int &ls, const int &rs) { return ls.x<rs; }
};
Int operator""_i(unsigned long long x) { return {int(x)}; }//}

inline int ceillog2(unsigned long long x) {
    return !x ? -1 : x==1 ? 0 : 64-__builtin_clzll(x-1);
}
template <class S,
          S (*op)(S lval, S rval, int l, int mid, int r),
          int e,
          class F,
          S (*mapping)(F lz, S val, int l, int r, int ul, int ur),
          F (*composition)(F plz, F lz, int l, int r, int ul, int ur),
          F id>
class lazy_segtree {
  public:
    lazy_segtree() : lazy_segtree(0) {}
    lazy_segtree(int _nn, S val = e, bool oneBased = 1) : lazy_segtree(std::vector<S>(_nn, val)) { if (val != e and oneBased) set(0, e); }
    lazy_segtree(const std::vector<S>& v) : _n(int(v.size())) {
        log = ceillog2(_n);
        size = _n ? 1 << log : 0;   // shifting by -1 is undefined
        d = std::vector<S>(2 * size, e);
        lz = std::vector<F>(size, id);
        range.resize(2 * size);
        copy_n(begin(v), _n, begin(d) + size);
        for (int i = 0; i < size; ++i) range[size + i] = {i, i+1};
        for (int i = size - 1; i >= 1; --i) {
            range[i] = {range[i << 1].first, range[i << 1 | 1].second};
            update(i);
        }
    }

    void set(int p, S x) {
        assert(0 <= p && p < _n);
        p += size;
        for (int i = log; i >= 1; --i) push(p >> i);
        d[p] = x;
        for (int i = 1; i <= log; ++i) update(p >> i);
    }

    S get(int p) {
        assert(0 <= p && p < _n);
        p += size;
        for (int i = log; i >= 1; --i) push(p >> i);
        return d[p];
    }

    S prod(int l, int r) { ++r;
        assert(0 <= l && l <= r && r <= _n);
        if (l == r) return e;

        int ql = l, qr = r;

        l += size;
        r += size;

        for (int i = log; i >= 1; --i) {
            if (((l >> i) << i) != l) push(l >> i);
            if (((r >> i) << i) != r) push(r >> i);
        }

        S sml = e, smr = e;
        while (l < r) {
            if (l & 1) sml = op(sml, d[l], ql, range[l].first, range[l].second), ++l;
            if (r & 1) --r, smr = op(d[r], smr, range[r].first, range[r].second, qr);
            l >>= 1;
            r >>= 1;
        }

        return op(sml, smr, ql, range[l].first, qr);
    }

    S all_prod() { return d[1]; }

    void apply(int p, F f) {
        assert(0 <= p && p < _n);
        p += size;
        for (int i = log; i >= 1; --i) push(p >> i);
        d[p] = mapping(f, d[p], p, p, p, p);
        for (int i = 1; i <= log; ++i) update(p >> i);
    }
    void apply(int l, int r, F f) { ++r;
        assert(0 <= l && l <= r && r <= _n);
        if (l == r) return;

        int ul = l, ur = r;

        l += size;
        r += size;

        for (int i = log; i >= 1; --i) {
            if (((l >> i) << i) != l) push(l >> i);
            if (((r >> i) << i) != r) push((r - 1) >> i);
        }

        {
            int l2 = l, r2 = r;
            while (l < r) {
                if (l & 1) all_apply(l, f, range[l].first, range[l].second, ul, ur), ++l;
                if (r & 1) --r, all_apply(r, f, range[r].first, range[r].second, ul, ur);
                l >>= 1;
                r >>= 1;
            }
            l = l2;
            r = r2;
        }

        for (int i = 1; i <= log; ++i) {
            if (((l >> i) << i) != l) update(l >> i);
            if (((r >> i) << i) != r) update((r - 1) >> i);
        }
    }

    template <bool (*g)(S, int, int)> int max_right(int l) {
        return max_right(l, [](S x, int cl, int cr) { return g(x, cl, cr); });
    }
    template <class G> int max_right(int l, G g) {
        assert(0 <= l && l <= _n);
        assert(g(e, 0, 0));
        if (l == _n) return _n;
        int ql = l;
        l += size;
        for (int i = log; i >= 1; --i) push(l >> i);
        S sm = e;
        do {
            while (!(l & 1)) l >>= 1;
            if (!g(op(sm, ql, range[l].first, range[l].second), ql, range[l].second)) {
                while (l < size) {
                    push(l);
                    l <<= 1;
                    auto tmp = op(sm, d[l], ql, range[l].first, range[l].second);
                    if (g(tmp, ql, range[l].second)) {
                        sm = tmp;
                        ++l;
                    }
                }
                return l - size;
            }
            sm = op(sm, d[l], ql, range[l].first, range[l].second);
            ++l;
        } while ((l & -l) != l);
        return _n;
    }

    template <bool (*g)(S, int, int)> int min_left(int r) {
        return min_left(r, [](S x, int cl, int cr) { return g(x, cl, cr); });
    }
    template <class G> int min_left(int r, G g) { ++r;
        assert(0 <= r && r <= _n);
        assert(g(e, 0, 0));
        if (r == 0) return 0;
        int qr = r;
        r += size;
        for (int i = log; i >= 1; --i) push((r - 1) >> i);
        S sm = e;
        do {
            --r;
            while (r > 1 && (r & 1)) r >>= 1;
            if (!g(op(d[r], sm, range[r].first, range[r].second, qr), range[r].first, qr)) {
                while (r < size) {
                    push(r);
                    r = r << 1 | 1;
                    auto tmp = op(d[r], sm, range[r].first, range[r].second, qr);
                    if (g(tmp, range[r].first, qr)) {
                        sm = tmp;
                        --r;
                    }
                }
                return r + 1 - size;
            }
            sm = op(d[r], sm, range[r].first, range[r].second, qr);
        } while ((r & -r) != r);
        return 0;
    }

    string toString(int nd = 26, bool printRange = false) {
        auto pad2 = [](const int &x)->string { return (" "+(x>=10)) + std::to_string(x); };
        ostringstream os;
        os << '\n';
        if (printRange) {
            for (int i = 0; i <= nd; ++i) {
                for (int j = i; j <= nd; ++j)
                    os << pad2(i) << ' ' << pad2(j) << " =  " << prod(i, j) << '\n';
            }
        } else {
            for (int i = 0; i <= nd; ++i) {
                os << pad2(i) << " =  " << prod(i, i) << '\n';
            }
        }
        return os.str();
    }

  private:
    int _n, size, log;
    std::vector<S> d;
    std::vector<F> lz;
    std::vector<pair<int,int>> range;

    void update(int k) { d[k] = op(d[k << 1], d[k << 1 | 1], range[k].first, range[k << 1].second, range[k].second); }
    void all_apply(int k, F f, int l, int r, int ul, int ur) {
        d[k] = mapping(f, d[k], l, r, ul, ur);
        if (k < size) lz[k] = composition(f, lz[k], l, r, ul, ur);
    }
    void push(int k) {
        all_apply(k << 1, lz[k], range[k << 1].first, range[k << 1].second, range[k].first, range[k].second);
        all_apply(k << 1 | 1, lz[k], range[k << 1 | 1].first, range[k << 1 | 1].second, range[k].first, range[k].second);
        lz[k] = id;
    }
};
Int p10[N],full[10][N];
#define unus __attribute__((unused))
namespace seg { // ranges are [l, r) here unlike update / query.
    using S = Int;
    using F = int;
    const S e = 0;
    const F id = 0;
    S op(S lval, S rval, unus int l, unus int mid, unus int r) { return lval*p10[r-mid]+rval; }  // merging [l, mid) and [mid, r)
    S mapping(F lz, unus S val, unus int l, unus int r, unus int ul, unus int ur) { return lz==id ? val : full[lz][r-l]; }
    F composition(F lz, unus F clz, unus int l, unus int r, unus int ul, unus int ur) { return lz==id ? clz : lz; }
    using tree = lazy_segtree<S, op, 0, F, mapping, composition, id>;
}
using segtr = seg::tree;

int TC=1, CN;

signed main() { cin.tie(0)->sync_with_stdio(0); cin.exceptions(cin.failbit); cout.precision(11), cout.setf(ios::fixed);
    //cin >> TC;// inputAll + resetAll -> solution
    for(int i=0;i<N;++i){
        p10[i]=i? p10[i-1]*10: 1;
        for(int j=1;j<=9;++j)full[j][i]=i? full[j][i-1]*10+j: 0;
    }
    auto kase = [&]()->void {
        int n,q;
        cin>>n>>q;
        segtr st(n+1,1);
        while(q--){
            int l,r,d;
            cin>>l>>r>>d;
            st.apply(l,r,d);
            cout<<st.prod(1,n)<<lf;
        }
    };
    while (CN++!=TC) kase();
}


Measured memory_bytes: 19032