#if local
#define _GLIBCXX_DEBUG
#endif

#include<bits/stdc++.h>
using namespace std;

#define rep(i,n) for(ll i=0;i<ll(n);++i)
#define repr(i,n) for(ll i=ll(n);i-->0;)
using ll = int_fast64_t;
using pll = pair<ll,ll>;
constexpr ll INF = 1LL<<60;
constexpr ll MOD = 1e9+7;
template<class T> bool chmax(T &a,const T &b){if(a<b){a=b;return 1;}return 0;}
template<class T> bool chmin(T &a,const T &b){if(a>b){a=b;return 1;}return 0;}
#if local
template<class T>void dump(T&& t){cerr<<t<<endl;}
template<class T,class... Ts> void dump(T&& h, Ts&&... t){cerr<<h<<", ";dump(forward<Ts>(t)...);}
#else
void dump(){}
template<class T,class... Ts> void dump(T&& h, Ts&&... t){}
#endif
template<class T> istream &operator>>(istream&is,vector<T>&v){for(auto &elemnt:v)is>>elemnt;return is;}
template<class T,class U> istream &operator>>(istream&is,pair<T,U>&p){is>>p.first>>p.second;return is;}
template<class T> ostream &operator<<(ostream& os,vector<T>const& v){for(auto const& vi:v)os<<vi<<" ";return os;}
template<class T,class U> ostream &operator<<(ostream& os,pair<T,U>const& p){os<<p.first<<","<<p.second;return os;}
template<class T>vector<T> vec(size_t a){return vector<T>(a);}
template<class T, class... Ts>auto vec(size_t a, Ts... ts){return vector<decltype(vec<T>(ts...))>(a, vec<T>(ts...));}

template<class T,class F>
struct segment_tree{
  std::vector<T> data;int n;F f;T identity;segment_tree(){}
  segment_tree(int sz,T ide,F _f):f(_f),identity(ide){n=1;while(n<sz)n<<=1;data.resize(2*n,identity);}
  segment_tree(std::vector<T> const& v,T ide,F _f):f(_f),identity(ide){int sz=v.size();n=1;while(n<sz)n<<=1;data.resize(2*n,identity);for(int i=0;i<sz;++i)data[i+n]=v[i];for(int i=n-1;i>0;--i)data[i]=f(data[i<<1|0],data[i<<1|1]);}
  void set(int i,T x){i+=n;data[i]=x;while(i,i>>=1)data[i]=f(data[i<<1|0],data[i<<1|1]);}
  T fold(int l,int r)const{l+=n,r+=n;T fold_l=identity,fold_r=identity;while(l<r){if(l&1)fold_l=f(fold_l,data[l++]);if(r&1)fold_r=f(data[--r],fold_r);l>>=1,r>>=1;}return f(fold_l,fold_r);}
  T fold()const{int l=n,r=2*n;T fold_l=identity,fold_r=identity;while(l<r){if(l&1)fold_l=f(fold_l,data[l++]);if(r&1)fold_r=f(data[--r],fold_r);l>>=1,r>>=1;}return f(fold_l,fold_r);}
  T operator[](int i)const{return data[i+n];}
  template<class Cond>int bserch(int l,Cond& cond){l+=n;T x=identity;do{while(!l&1)l>>=1;if(cond(f(x,data[l]))){while(l<n){l<<=1;if(!cond(f(x,data[l])))x=f(x,data[l++]);}return l-n;}x=f(x,data[l++]);}while((l&-l)!=l);return -1;}
};
template<class T,class F>auto make_segtree(int n,T ide,F f){return segment_tree<T,F>(n,ide,f);}
template<class T,class F>auto make_segtree(std::vector<T>const& v,T ide,F f){return segment_tree<T,F>(v,ide,f);}
auto RMQ(int n=2e5){return make_segtree<int64_t>(n,-(1ll<<60),[](auto a,auto b){return a>b?a:b;});}auto rmq(int n=2e5){return make_segtree<int64_t>(n,1ll<<60,[](auto a,auto b){return a<b?a:b;});}auto rsq(int n=2e5){return make_segtree<int64_t>(n,0,[](auto a,auto b){return a+b;});}

struct union_find{
  size_t n;std::vector<int> par;size_t group;union_find(){}
  union_find(size_t _n):n(_n),group(_n){par.resize(n,-1);}
  void reset      (size_t _n)     {n = _n;group = n;par.clear();par.resize(n,-1);}
  int  root       (int k)         {if(par[k]<0)return k;return par[k]=root(par[k]);}
  int  size       (int k)         {k=root(k);return -par[k];}
  bool unite      (int a,int b)   {a=root(a);b=root(b);if(a==b)return false;if(size(a)<size(b))std::swap(a,b);group--;par[a]+=par[b];par[b]=a;return true;}
  bool same       (int a,int b)   {return root(a) == root(b);}
  int  operator[] (int k)         {return size(k);}
  bool operator() (int a,int b)   {return unite(a,b);}
};

template<class T,class U,class F,class G,class H>
struct lazy_segment_tree{
  std::vector<T> data;
  std::vector<U> lazy;
  int n,height;
  F merge;
  G mapping;
  H composition;
  T ti;
  U ui;
  lazy_segment_tree(){}
  lazy_segment_tree(std::vector<T>const& v,T ide1,U ide2,F f,G g,H h)
    :ti(ide1),ui(ide2),merge(f),mapping(g),composition(h)
  {
    int sz = std::size(v);
    n=1,height=0;
    while(n<sz)n<<=1,height++;
    data.resize(n<<1,ti);
    lazy.resize(n<<1,ui);
    for(int i=0;i<sz;++i)
      data[i+n] = v[i];
    for(int i=n;i-->0;)
      data[i] = merge(data[i<<1|0],data[i<<1|1]);
  }
  inline T reflect(int k){
    return lazy[k]==ui?data[k]:mapping(data[k],lazy[k]);
  }
  inline void evaluate(int k){
    if(lazy[k]==ui)return;
    if(k<n){
      lazy[k<<1|0] = composition(lazy[k<<1|0],lazy[k]);
      lazy[k<<1|1] = composition(lazy[k<<1|1],lazy[k]);
    }
    data[k] = reflect(k);
    lazy[k] = ui;
  }
  inline void propagate(int k){
    for(int i=height;i>=0;--i)evaluate(k>>i);
  }
  inline void recalc(int k){
    while(k>>=1)data[k] = merge(reflect(k<<1|0),reflect(k<<1|1));
  }
  void update(int a,int b,U v){
    a+=n;b+=n;propagate(a);propagate(b-1);
    for(int l=a,r=b;l<r;l>>=1,r>>=1){
      if(l&1)lazy[l] = composition(lazy[l],v),l++;
      if(r&1)--r,lazy[r] = composition(lazy[r],v);
    }
    recalc(a);recalc(b-1);
  }
  T fold(int a,int b){
    a+=n;b+=n;propagate(a),propagate(b-1);
    T lef_v(ti),rig_v(ti);
    for(int l=a,r=b;l<r;l>>=1,r>>=1){
      if(l&1)lef_v = merge(lef_v,reflect(l)),l++;
      if(r&1)--r,rig_v = merge(reflect(r),rig_v);
    }
    return merge(lef_v,rig_v);
  }
  T fold_all(){
    return data[1];
  }
  T operator[](int k){
    k+=n;propagate(k);
    return data[k];
  }
};
template<class T,class U,class F,class G,class H>
auto make_lseg(std::vector<T> v,T ide1,U ide2,F f,G g,H h){
  return lazy_segment_tree<T,U,F,G,H>(v,ide1,ide2,f,g,h);
}

namespace ate{
  template<int64_t p>
  struct F_p{
    using value_type = int64_t;
    static constexpr inline value_type get_mod(){return p;}
    value_type value;
    constexpr F_p():value(value_type{}){}
    template<class T>constexpr F_p(T v):value(static_cast<value_type>(v<0?v%p+p:v%p)){}
  // operator +, -, *, /, ^ 
    constexpr F_p  operator +  (const F_p& other)const{return F_p(*this) += other;}
    constexpr F_p  operator -  (const F_p& other)const{return F_p(*this) -= other;}
    constexpr F_p  operator *  (const F_p& other)const{return F_p(*this) *= other;}
    constexpr F_p  operator /  (const F_p& other)const{return F_p(*this) /= other;}
    constexpr F_p &operator += (const F_p& other){value+=other.value;if(value>p)value-=p;return *this;}
    constexpr F_p &operator -= (const F_p& other){value-=other.value;if(value<0)value+=p;return *this;}
    constexpr F_p &operator *= (const F_p& other){value*=other.value;if(value>p)value%=p;return *this;}
    constexpr F_p &operator /= (const F_p& other){value*=other.inverse();if(value>p)value%=p;return *this;}
  // ext_gcd,inverse,mpow 
    static constexpr value_type ext_gcd(value_type a,value_type b,value_type& x,value_type& y){
      if(b==0){x=1,y=0;return a;}value_type d=ext_gcd(b,a%b,y,x);y-=a/b*x;return d;
    }
    constexpr value_type inverse()const{
      value_type x,y;ext_gcd(value,p,x,y);return x<0?x%p+p:x%p;
    }
    template<class T>
    static constexpr value_type inverse(T val){
      value_type x,y;ext_gcd(val,p,x,y);return x<0?x%p+p:x%p;
    }
    template<class T>
    constexpr F_p mpow(T n)const{
      F_p res(1),vn(*this);while(n){if(n&1)res*=vn;vn*=vn;n>>=1;}return res;
    }
    template<class T,class U>
    static constexpr T mpow(T a,U b){
      F_p x(a);return static_cast<T>(x.mpow(b).value);
    }
  // operator iostream 
    constexpr friend std::istream &operator >> (std::istream& is,F_p& fp){return is>>fp.value;}
    constexpr friend std::ostream &operator << (std::ostream& os,const F_p& fp){return os<<fp.value;}
  //operator bool
    constexpr bool operator == (const F_p& other)const{return value == other.value;}
  };
}
using mint = ate::F_p<998244353>;

signed main(){
  std::cin.tie(nullptr);
  std::ios_base::sync_with_stdio(false);
  constexpr char newl = '\n';

  int n,q;
  cin>>n>>q;
  
  vector<mint> tenpow(n+1);
  tenpow[0] = 1;
  rep(i,n)tenpow[i+1]=tenpow[i]*10;
  vector<vector<mint>> tapu(10,vector<mint>(n+1));
  rep(i,10)tapu[i][1]=i;
  rep(i,10)for(int j=1;j<n;++j)tapu[i][j+1]=tapu[i][j]*10+i;

  struct ushi{
    mint val;
    int sz;
    ushi():val(),sz(0){}
    ushi(mint v,int s):val(v),sz(s){}
  };
  auto merge = [&tenpow](ushi a,ushi b){return ushi(a.val*tenpow[b.sz]+b.val,a.sz+b.sz);};
  auto mapping = [&tapu](ushi a,ll b){return ushi(tapu[b][a.sz],a.sz);};
  auto composition = [](ll a,ll b){return b;};
  vector<ushi> a(n);
  rep(i,n)a[i] = ushi(1,1);
  ushi ti = ushi(0,0);
  ll ui = -1;
  auto seg = make_lseg<ushi,ll>(a,ti,ui,merge,mapping,composition);

  rep(i,q){
    int l,r,d;
    cin>>l>>r>>d;
    l--;r--;
    seg.update(l,r+1,d);
    mint ans = seg.fold_all().val;
    cout<<ans<<newl;
    if(i>100)continue;
    mint uku = 0;
    rep(i,n)uku=uku*10+seg[i].val;
    assert(ans==uku);
  }

}

Measured memory_bytes: 39028