#include<bits/stdc++.h>
using namespace std;
using ll = long long;
#define _overload3(_1,_2,_3,name,...) name
#define _rep(i,n) repi(i,0,n)
#define repi(i,a,b) for(int i=int(a);i<int(b);++i)
#define rep(...) _overload3(__VA_ARGS__,repi,_rep,)(__VA_ARGS__)
#define VIEW(x) do {cerr << #x << ": "; for(auto i : x) cerr << i << " "; cerr << endl;} while(0)
#define ALL(x) (x).begin(),(x).end()
template<class T>bool umax(T &a, const T &b) {if(a<b){a=b;return 1;}return 0;}
template<class T>bool umin(T &a, const T &b) {if(b<a){a=b;return 1;}return 0;}

template<typename A,size_t N,typename T> void FILL(A (&array)[N],const T &val){fill((T*)array,(T*)(array+N),val);}
template<typename T> void FILL(vector<T> &v, const T &x) {fill(v.begin(), v.end(), x);}
template<typename T> void FILL(vector<vector<T>> &v, const T &x) {for(auto &i:v)fill(i.begin(), i.end(), x);}

const int MOD = 998244353;
struct modint {
  long long val;
  modint(long long val=0) : val((val % MOD + MOD) % MOD){}
  modint operator-() const { return modint(-val); }
  modint& operator+=(const modint a) { if ((val += a.val)     >= MOD) val -= MOD; return *this; }
  modint& operator-=(const modint a) { if ((val += MOD-a.val) >= MOD) val -= MOD; return *this; }
  modint& operator*=(const modint a) { (val *= a.val) %= MOD; return *this; }
  modint operator+(const modint a) const { return (modint)*this += a; }
  modint operator-(const modint a) const { return (modint)*this -= a; }
  modint operator*(const modint a) const { return (modint)*this *= a; }
  modint pow(long long n) const { modint r(1), m(val); while (n > 0) { if (n & 1) {r *= m;} m *= m; n >>= 1; } return r; }
  modint inv() const { return pow(MOD-2); }
  modint& operator/=(const modint a) { return (*this) *= a.inv(); }
  modint operator/(const modint a) const { return (modint)*this /= a; }
  bool operator==(const modint &p) const { return val == p.val; }
  bool operator!=(const modint &p) const { return val != p.val; }
  friend ostream &operator<<(ostream &os, const modint &p) { return os << p.val; }
  friend istream &operator>>(istream &is, modint &a) { long long t; is >> t; a = modint(t); return (is); }
};

const modint inv9 = modint(1)/9;

template <class S,
          S (*op)(S, S),
          S (*e)(),
          class F,
          S (*mapping)(F, S),
          F (*composition)(F, F),
          F (*id)()>
struct lazy_segment_tree {
  int n, leafs;
  vector<S> node;
  vector<F> lazy;

  lazy_segment_tree(int n) : lazy_segment_tree(vector<S>(n, e())) {}
  lazy_segment_tree(const vector<S>& initial) : n(int(initial.size())) {
    /* O(n) */
    int msb = 1LL << ((n==0) ? 0 : 64 - __builtin_clzll(n)-1);
    leafs = (n==msb) ? n : msb << 1;
    node = vector<S>(2 * leafs - 1, e());
    lazy = vector<F>(2 * leafs - 1, id());
    for(int i=0; i<n; i++) node[i+leafs-1] = initial[i];
    for(int i=leafs-2; i>=0; --i) node[i] = op(node[l_child(i)], node[r_child(i)]);
  }

  inline int r_child(int v) { return v*2+2; }
  inline int l_child(int v) { return v*2+1; }
  inline int parent(int v) { return (v+1)/2-1; }
  inline bool is_leaf(int v) { return v >= (leafs-1); }

  void lazy_update(int v) { 
    /* O(1) */
    node[v] = mapping(lazy[v], node[v]);
    if ( !is_leaf(v) ) {
      lazy[l_child(v)] = composition(lazy[v], lazy[l_child(v)]);
      lazy[r_child(v)] = composition(lazy[v], lazy[r_child(v)]);
    }
    lazy[v] = id();
  }

  S product(int l, int r, int v=0, int vl=0, int vr=-1) { /* [l, r) */
    /* O(log n) */
    assert(l >=0 && l <= n);
    assert(r >=0 && r <= n);
    vr = (vr==-1) ? leafs : vr;
    lazy_update(v);
    if(l<=vl && vr<=r) return node[v];
    S ret = e(); int mid=(vl+vr)/2;
    if(l < mid) ret = op(product(l, r, l_child(v), vl, mid),ret);
    if(r > mid) ret = op(ret,product(l, r, r_child(v), mid, vr));
    return ret;
  }

  void apply(int l, int r, F f, int v=0, int vl=0, int vr=-1) { /* [l, r) */
    /* O(log n) */
    assert(l >=0 && l <= n);
    assert(r >=0 && r <= n);
    vr = (vr==-1) ? leafs : vr;
    lazy_update(v);
    if(l >= vr || r <= vl) return;
    if(l<=vl && vr<=r) {
      lazy[v] = composition(f, lazy[v]);
      lazy_update(v);
    }
    else {
      int mid=(vl+vr)/2;
      apply(l, r, f, l_child(v), vl, mid);
      apply(l, r, f, r_child(v), mid, vr);
      node[v] = op(node[l_child(v)], node[r_child(v)]);
    }
  }

  void lazy_update_all_ancestors(int v) {
    /* O(log n) */
    vector<int> path_to_root;
    for(int u = parent(v); u != -1; u=parent(u)) path_to_root.push_back(u);
    for(auto itr = rbegin(path_to_root); itr != rend(path_to_root); ++itr) lazy_update(*itr);
  }

  void set(int index, S s) {
    /* O(log n) */
    int v = index + (leafs-1);
    lazy_update_all_ancestors(v);
    node[v] = s;
    while((v=parent(v)) != -1) node[v] = op(node[r_child(v)], node[l_child(v)]);
  }

  void get(int index, S s) {
    /* O(log n) */
    int v = index + (leafs-1);
    lazy_update_all_ancestors(v);
    return node[v];
  }
};

struct S {
  modint x, power;
};
S op(S l, S r) { return S{l.x * r.power + r.x, l.power * r.power}; }
S e() { return S{0, 1}; }

struct F { int d; };
S mapping(F f, S s) {
  if(f.d == 0) return s;
  return S{(s.power-1) * inv9 * f.d, s.power};
}
F composition(F f, F g) {
  if( f.d == 0) return g;
  else return f;
}
F id() { return F{0}; }

int main() {
  int n,q; cin >> n >> q;
  vector<S> initial(n, {1,10});
  lazy_segment_tree<S, op, e, F, mapping, composition, id> t(initial);
  rep(i,q) {
    int l, r, d;
    cin >> l >> r >> d; --l;
    t.apply(l, r, F{d});
    S ans = t.product(0,n);
    cout << ans.x << endl;
  }
}


Measured memory_bytes: 16708