#include <bits/stdc++.h>
using namespace std;
// #include <ext/pb_ds/assoc_container.hpp> 
// #include <ext/pb_ds/tree_policy.hpp> 
// using namespace __gnu_pbds; 
// #pragma GCC target ("avx2")
// #pragma GCC optimization ("O3")
// #pragma GCC optimization ("unroll-loops")
#define fi first
#define se second
#define endl '\n'
// #define int
#define double long double
// template<int D, typename T>struct dense:public vector<dense<D-1,T>>{static_assert(D>=1,"dim err");template<typename... Args>dense(int n=0,Args... args):vector<dense<D-1,T>>(n,dense<D-1,T>(args...)){}};
// template<typename T>struct dense<1,T>:public vector<T>{dense(int n=0,const T& val=T()):vector<T>(n,val){}};
// template<typename T> using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
// template<typename T> using reverse_queue = priority_queue<T, vector<T>, greater<T>>;
// mt19937_64 rnd(time(0));
// const int FIXED_RANDOM = rnd();
// template<typename T> struct custom_hash{T operator()(T x)const{return (T) x^FIXED_RANDOM;}}; // check hash in whether int64 or int32
// template<typename T1, typename T2> using hash_map = gp_hash_table<T1, T2, custom_hash<T1>>;
const int MAXN = (int) 3e5 + 2;
const int INF = numeric_limits<int>::max() >> 1;
const int MOD = (int) 998244353;
// Tao luyện kỹ thuật trong 8 năm mày luyện kỹ thuật trong buồng tắm nam
template<int mod=MOD> struct int_mod{
  int64_t x;
  int_mod():x(0){} int_mod(int64_t y):x(y>=0?y%mod:(mod-(-y)%mod)%mod){}
  int_mod &operator+=(const int_mod &p){if((x+=p.x)>=mod)x-=mod;return *this;}
  int_mod &operator-=(const int_mod &p){if((x+=mod-p.x)>=mod)x-=mod;return *this;}
  int_mod &operator*=(const int_mod &p){x=(int64_t)(1LL*x*p.x%mod);return *this;}
  int_mod &operator/=(const int_mod &p){*this *=p.inv();return *this;}
  int_mod operator-()const{return int_mod(-x);}
  int_mod operator+(const int_mod &p)const{return int_mod(*this)+=p;}
  int_mod operator-(const int_mod &p)const{return int_mod(*this)-=p;}
  int_mod operator*(const int_mod &p)const{return int_mod(*this)*=p;}
  int_mod operator/(const int_mod &p)const{return int_mod(*this)/=p;}
  bool operator==(const int_mod &p)const{return x==p.x;}
  bool operator!=(const int_mod &p)const{return x!=p.x;}
  int_mod inv()const{int64_t a=x,b=mod,u=1,v=0,t;while(b>0){t=a/b;swap(a-=t*b,b);swap(u-=t*v,v);}return int_mod(u);}
  int_mod pow(int64_t n)const{int_mod ret(1),mul(x);while(n){if(n&1)ret*=mul;mul*=mul;n>>=1;}return ret;}
  friend ostream &operator<<(ostream &os,const int_mod &p){return os<<p.x;}
  friend istream &operator>>(istream &is,int_mod &a){int64_t t;is>>t;a=int_mod<mod>(t);return(is);}
};
struct lazy_segment_tree{
  using it_type = int_mod<>;
  int n;
  vector<it_type> it;
  vector<int> lz;
  vector<it_type> p10;
  vector<it_type> pref;
  const it_type FAILED_STAGE = 0;
  void init(int _){
    n = _;
    p10.resize(n);
    pref.resize(n);
    for(int i = 0; i < n; i ++){
      p10[i] = int_mod<>(10).pow(i);
      if(i) pref[i] = pref[i - 1] + p10[i];
      else pref[i] = p10[i];
    }
    it.resize((n << 2)|1);
    lz.resize((n << 2)|1, -1); // check init lazy
  }
  it_type merge(it_type a, it_type b){
    return a + b;
  }
  it_type build(int u, int l, int r, vector<it_type> &a){ // 1 indexed
    if(l == r) return it[u] = a[l]*p10[l - 1];
    return it[u] = merge(build(u << 1, l, ((l + r)>>1), a), build((u << 1)|1, ((l + r)>>1) + 1, r, a)); // merge stage
  }
  void lazy(int u, int l, int r){ // lazy 
    if(lz[u] == -1) return;
    it_type zz = pref[(int)r - 1];
    if(l > 1) zz -= pref[(int)l - 2];
    it[u] = zz*lz[u];
    if(l != r){
      lz[u << 1] = lz[u];
      lz[(u << 1)|1] = lz[u];
    }
    lz[u] = -1;
  }
  void update(int u, int l, int r, int L, int R, int val){
    if(R < L) return;
    lazy(u, l, r);
    if(l > R || r < L) return;
    if(L <= l && r <= R){
      lz[u] = val; // lazy update 
      lazy(u, l, r);
      return;
    }
    update(u << 1, l, ((l + r)>>1), L, R, val);
    update((u << 1)|1, ((l + r)>>1) + 1, r, L, R, val);
    it[u] = merge(it[u << 1], it[(u << 1)|1]); // merge stage
  }
  it_type get(int u, int l, int r, int L, int R){
    if(l > R || r < L) return FAILED_STAGE; // check for failed stage
    lazy(u, l, r);
    if(L <= l && r <= R) return it[u];
    return merge(get(u << 1, l, ((l + r)>>1), L, R), get((u << 1)|1, ((l + r)>>1) + 1, r, L, R)); // merge stage
  }
};
signed main(){
  ios_base::sync_with_stdio(0); 
  cin.tie(0);
  // freopen("FDT.txt", "r", stdin);
  int n, q;
  cin >> n >> q;
  lazy_segment_tree tr;
  tr.init(n);
  vector<int_mod<>> a(n + 1, 1);
  // for(int i = 0; i < n; i ++) cout << tr.pref[i] << " ";
  tr.build(1, 1, n, a);
  while(q --){
    int l, r, d;
    cin >> l >> r >> d;
    l = n + 1 - l;
    r = n + 1 - r;
    swap(l ,r);
    tr.update(1, 1, n, l, r, d);
    cout << tr.get(1, 1, n, 1, n) << endl;
  }
}


Measured memory_bytes: 17184