#pragma region template
// clang-format off
#if defined ONLINE_JUDGE
  #pragma GCC target("avx2")
  #pragma GCC optimize("tree-vectorize")
  #define here(...)
  #define com(msg)
  #define watch(...)
  #define watchVec(vec)
  #define local(x)
  #define alter(x,y) y
  #define M_assert(expr) do{if(!expr) vector<int> MLE_(3e8, 0);} while(0)
  #define O_assert(expr) do{if(!expr) while(1) printf("Hello, world!\n");} while(0)
#elif defined LOCAL_JUDGE
  #pragma GCC target("avx2")
  #pragma GCC optimize("tree-vectorize")
  #define here(...)
  #define com(msg)
  #define watch(...)
  #define watchVec(vec)
  #define local(x)
  #define alter(x,y) y
  #define M_assert(expr) assert(expr)
  #define O_assert(expr) assert(expr)
#else
  #define here(...) cerr<<"[Debug] "<<__func__<<"/"<<__LINE__<<" : reached "<<#__VA_ARGS__<<"\n"
  #define com(msg) cerr<<"[Debug] "<<msg<<"\n"
  #define watch(...) dbg1(#__VA_ARGS__,__VA_ARGS__)
  #define watchVec(vec) do{cerr<<#vec<<": ";dbg2(#vec,vec);} while(0)
  #define local(x) do{x} while(0)
  #define alter(x,y) x
  #define M_assert(expr) assert(expr)
  #define O_assert(expr) assert(expr)
#endif

#include <bits/stdc++.h>
#include <boost/range/irange.hpp>
#include <boost/multiprecision/cpp_int.hpp>
#include <atcoder/all>
namespace ac = atcoder;

#define rep(i,n) for(int i=0;i<(n);i++)
#define rng(i,f,t,s) for(int i : boost::irange(f,t,s))
#define erng(i,f,t,s) for(int i : boost::irange(f,t+(s>0)-(s<0),s))
#define yes(n) cout<<((n)?YES:NO)<<"\n"
#define Sort(v) sort((v).begin(),(v).end())
#define rSort(v) sort((v).rbegin(),(v).rend())
#define Rev(v) reverse((v).begin(),(v).end())
#define Unique(v) (v).erase(unique((v).begin(),(v).end()),(v).end())
#define inarea(p,a,b) (0<=(p.first)&&0<=(p.second)&&(p.first)<(a)&&(p.second)<(b))
#define in_area(y,x,a,b) (0<=(y)&&0<=(x)&&(y)<(a)&&(x)<(b))
#define in_range(x,a,b) ((a)<=(x)&&(x)<(b))

using namespace std;
using Int = boost::multiprecision::cpp_int;

constexpr int           INF   = 1e9;
constexpr long long     LINF  = 1e18;
constexpr double        EPS   = 1e-9;
constexpr int           MOD   = 998244353;
constexpr int           dy[]  = {1,0,-1,0,1,1,-1,-1};
constexpr int           dx[]  = {0,1,0,-1,-1,1,1,-1};
constexpr pair<int,int> dv[]  = { {1,0},{0,1},{-1,0},{0,-1},{1,-1},{1,1},{-1,1},{-1,-1} };

// --- functions for debugging --- //
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
template<class T>            void dbg1(const char *n, T &&v){cerr<<n<<": "<<v<<"\n";}
template<class S,class... T> void dbg1(const char *n, S &&v, T&&... w){const char *c=strchr(n+1,',');cerr.write(n,c-n)<<": "<<v<<" |";dbg1(c+1,w...);}
template<class T>            void dbg2(const char *n, vector<vector<T>> &v){bool f=0;for(const vector<T> &x:v){if(f)cerr<<string(strlen(n)+2,' ');f=1;dbg2<T>("",x);}}
template<class T>            void dbg2(const char *n, vector<deque<T>> &v){bool f=0;for(const deque<T> &x:v){if(f)cerr<<string(strlen(n)+2,' ');f=1;dbg2<T>("",x);}}
template<class T>            void dbg2(const char *n, vector<T> &v){cerr<<"[ ";for(auto &&x:v)cerr<<x<<" ";cerr<<"]\n";}
template<class T>            void dbg2(const char *n, deque<T> &v){cerr<<"[ ";for(const T &x:v)cerr<<x<<" ";cerr<<"]\n";}
template<class T>            void dbg2(const char *n, set<T> &v){cerr<<"[ ";for(const T &x:v)cerr<<x<<" ";cerr<<"]\n";}
template<class P>            void dbg2(const char *n, P &p){cerr<<"{ "<<p.first<<" "<<p.second<<" } ";}
template<class S,class T>    void dbg2(const char *n, map<S,T> &m){cerr<<"[ ";for(const pair<S,T> &p:m)cerr<<"{ "<<p.first<<", "<<p.second<<" } ";cerr<<"]\n";}
template<class S,class T>    void dbg2(const char *n, vector<pair<S,T>> &v){cerr<<"[ ";for(const pair<S,T> &p:v)dbg2<pair<S,T>>("",p);cerr<<"]\n";}
template<class S,class T>    void dbg2(const char *n, deque<pair<S,T>> &v){cerr<<"[ ";for(const pair<S,T> &p:v)dbg2<pair<S,T>>("",p);cerr<<"]\n";}
#pragma GCC diagnostic pop
// clang-format on
#pragma endregion
// mod

#pragma region lib_mint
/*
  class mint (mod int)
  requires: constexpr int MOD = *** (e.g. 1000000007)
*/
#ifndef lib_mint
#define lib_mint 1
namespace lib {
  template <class T = long long> constexpr T modinv(long long n, int mod = MOD) {
    int a = n, b = mod, u = 1, v = 0, t = 0;
    while (b > 0) {
      t = a / b;
      swap(a -= t * b, b);
      swap(u -= t * v, v);
    }
    return (T) u;
  }

  template <class T> constexpr int_fast32_t clamp_ll(T v) {
    if (0 <= v && v < MOD) return (int_fast32_t) v;
    if (MOD <= v && v < (MOD << 1)) return (int_fast32_t)(v - MOD);
    if (-MOD <= v && v < 0) return (int_fast32_t)(v + MOD);
    if (0 <= v)
      return (int_fast32_t)(v - v / MOD * MOD);
    else
      return (int_fast32_t)(v + (-v + MOD - 1) / MOD * MOD);
  }

  class mint {
    public:
    template <class T = int_fast32_t> constexpr mint(T v = 0) :
        val(clamp_ll(v)) {}

#define MINT_PREFIX_OP(o)        \
  constexpr mint &operator o() { \
    (this->val) o;               \
    this->clamp();               \
    return *this;                \
  }
    MINT_PREFIX_OP(++)
    MINT_PREFIX_OP(--)
#undef MINT_PREFIX_OP

#define MINT_POSTFIX_OP(o)         \
  constexpr mint operator o(int) { \
    mint ret = *this;              \
    o(*this);                      \
    return ret;                    \
  }
    MINT_POSTFIX_OP(++)
    MINT_POSTFIX_OP(--)
#undef MINT_POSTFIX_OP

#define MINT_UNARY_OP(o)              \
  constexpr mint operator o() const { \
    return mint(o(this->val));        \
  }
    MINT_UNARY_OP(+)
    MINT_UNARY_OP(-)
    MINT_UNARY_OP(~)
#undef MINT_UNARY_OP

    constexpr bool operator!() const {
      return !(this->val);
    }

#define MINT_BOOLEAN_OP(o)                    \
  constexpr bool operator o(mint rhs) const { \
    return (this->val o rhs.val);             \
  }
    MINT_BOOLEAN_OP(==)
    MINT_BOOLEAN_OP(!=)
    MINT_BOOLEAN_OP(<)
    MINT_BOOLEAN_OP(<=)
    MINT_BOOLEAN_OP(>)
    MINT_BOOLEAN_OP(>=)
    MINT_BOOLEAN_OP(&&)
    MINT_BOOLEAN_OP(||)
#undef MINT_BOOLEAN_OP

#define MINT_TEMP_BOOLEAN_OP(o)                               \
  template <class T> constexpr bool operator o(T rhs) const { \
    return (this->val o rhs);                                 \
  }
    MINT_TEMP_BOOLEAN_OP(==)
    MINT_TEMP_BOOLEAN_OP(!=)
    MINT_TEMP_BOOLEAN_OP(<)
    MINT_TEMP_BOOLEAN_OP(<=)
    MINT_TEMP_BOOLEAN_OP(>)
    MINT_TEMP_BOOLEAN_OP(>=)
    MINT_TEMP_BOOLEAN_OP(&&)
    MINT_TEMP_BOOLEAN_OP(||)
#undef MINT_TEMP_BOOLEAN_OP

#define MINT_COMPOUND_OP(o)                                   \
  [[maybe_unused]] constexpr mint &operator o##=(mint rhs) {  \
    this->val = clamp_ll((int_fast64_t) this->val o rhs.val); \
    return *this;                                             \
  }
    MINT_COMPOUND_OP(+)
    MINT_COMPOUND_OP(-)
    MINT_COMPOUND_OP(*)
    MINT_COMPOUND_OP(%)
    MINT_COMPOUND_OP(&)
    MINT_COMPOUND_OP(|)
    MINT_COMPOUND_OP(^)
    MINT_COMPOUND_OP(<<)
    MINT_COMPOUND_OP(>>)
#undef MINT_COMPOUND_OP

#define MINT_TEMP_COMPOUND_OP(o)                                            \
  template <class T>[[maybe_unused]] constexpr mint &operator o##=(T rhs) { \
    this->val = (*this o mint(rhs));                                        \
    this->clamp();                                                          \
    return *this;                                                           \
  }
    MINT_TEMP_COMPOUND_OP(+)
    MINT_TEMP_COMPOUND_OP(-)
    MINT_TEMP_COMPOUND_OP(*)
    MINT_TEMP_COMPOUND_OP(%)
    MINT_TEMP_COMPOUND_OP(&)
    MINT_TEMP_COMPOUND_OP(|)
    MINT_TEMP_COMPOUND_OP(^)
    MINT_TEMP_COMPOUND_OP(<<)
    MINT_TEMP_COMPOUND_OP(>>)
#undef MINT_TEMP_COMPOUND_OP

    template <class T>[[maybe_unused]] constexpr mint &operator/=(T divided_by) {
      assert(divided_by != 0);
      return *this *= modinv(divided_by);
    }

#define MINT_OP(o)                            \
  constexpr mint operator o(mint rhs) const { \
    return mint(*this) o## = rhs;             \
  }
    MINT_OP(+)
    MINT_OP(-)
    MINT_OP(*)
    MINT_OP(/)
    MINT_OP(%)
    MINT_OP(&)
    MINT_OP(|)
    MINT_OP(^)
    MINT_OP(<<)
    MINT_OP(>>)
#undef MINT_OP

#define MINT_TEMP_OP(o)                                       \
  template <class T> constexpr mint operator o(T rhs) const { \
    return *this o mint(rhs);                                 \
  }
    MINT_TEMP_OP(+)
    MINT_TEMP_OP(-)
    MINT_TEMP_OP(*)
    MINT_TEMP_OP(%)
    MINT_TEMP_OP(&)
    MINT_TEMP_OP(|)
    MINT_TEMP_OP(^)
    MINT_TEMP_OP(<<)
    MINT_TEMP_OP(>>)
#undef MINT_TEMP_OP

#define MINT_CAST_OP(t)               \
  constexpr operator t() const {      \
    return static_cast<t>(this->val); \
  }
    MINT_CAST_OP(bool)
    MINT_CAST_OP(char)
    MINT_CAST_OP(signed char)
    MINT_CAST_OP(unsigned char)
    MINT_CAST_OP(short int)
    MINT_CAST_OP(unsigned short int)
    MINT_CAST_OP(int)
    MINT_CAST_OP(unsigned int)
    MINT_CAST_OP(long int)
    MINT_CAST_OP(unsigned long int)
    MINT_CAST_OP(long long int)
    MINT_CAST_OP(unsigned long long int)
    MINT_CAST_OP(float)
    MINT_CAST_OP(double)
    MINT_CAST_OP(long double)
#undef MINT_CAST_OP
#ifdef BOOST_MP_CPP_INT_HPP
    operator boost::multiprecision::cpp_int() const {
      return static_cast<boost::multiprecision::cpp_int>(this->val);
    }
#endif

    constexpr mint inverse() {
      return modinv<mint>(this->val);
    }

    friend istream &operator>>(istream &, mint &);
    friend ostream &operator<<(ostream &, mint);

    private:
    int_fast32_t val;

    constexpr void clamp() {
      if (0 <= (this->val) && (this->val) < MOD) return;
      if (MOD <= (this->val) && (this->val) < (MOD << 1)) {
        (this->val) -= MOD;
        return;
      }
      if (-MOD <= (this->val) && (this->val) < 0) {
        (this->val) += MOD;
        return;
      }

      if (0 <= (this->val))
        (this->val) -= (this->val) / MOD * MOD;
      else
        (this->val) += (-(this->val) + MOD - 1) / MOD * MOD;
    }
  };

  istream &operator>>(istream &is, mint &m) {
    return is >> m.val;
  }
  ostream &operator<<(ostream &os, mint m) {
    return os << m.val;
  }

}  // namespace lib

template <class T> struct common_type<lib::mint, T> { using type = lib::mint; };
using mint   = lib::mint;
using vmint  = vector<mint>;
using vvmint = vector<vector<mint>>;
#endif
#pragma endregion

vmint ten_to_the_n(300000);
vmint repunit(300000);

struct S {
  mint val;
  int size;
};

constexpr mint ID = (mint) 2e9;

S op(S a, S b) {
  return {a.val * ten_to_the_n[b.size] + b.val, a.size + b.size};
}

S e() {
  return {0, 0};
}

S mapping(mint f, S x) {
  if (f != ID) x.val = f * repunit[x.size];
  return x;
}

mint composition(mint f, mint g) {
  return (f == ID ? g : f);
}

mint id() {
  return ID;
}

void solve(int N, int Q, vector<int> L, vector<int> R, vector<int> D) {
  ten_to_the_n[0] = 1;
  repunit[0]      = 0;

  for (int i = 1; i < (int) ten_to_the_n.size(); i++)
    ten_to_the_n[i] = ten_to_the_n[i - 1] * 10;
  for (int i = 1; i < (int) repunit.size(); i++)
    repunit[i] = repunit[i - 1] * 10 + 1;

  ac::lazy_segtree<S, op, e, mint, mapping, composition, id> seg(vector<S>(N, {1, 1}));

  for (int i = 0; i < Q; i++) {
    seg.apply(L[i] - 1, R[i], D[i]);
    cout << seg.all_prod().val << "\n";
  }
}

// clang-format off
int main() {
  #pragma GCC diagnostic push
  #pragma GCC diagnostic ignored "-Wunused-result"
  int N;
  scanf("%d",&N);
  int Q;
  scanf("%d",&Q);
  vector<int> L(Q);
  vector<int> R(Q);
  vector<int> D(Q);
  for(int i = 0 ; i < Q ; i++){
    scanf("%d",&L[i]);
    scanf("%d",&R[i]);
    scanf("%d",&D[i]);
  }
  #pragma GCC diagnostic pop
  solve(N, Q, move(L), move(R), move(D));
  exit(EXIT_SUCCESS);
}


Measured memory_bytes: 23640