#include <algorithm>
#include <cmath>
#include <cstddef>
#include <functional>
#include <initializer_list>
#include <iostream>
#include <vector>
using namespace std;
template <typename T, typename E> class LazySegmentTree {
  using F = function<T(T, T)>;
  using G = function<T(T, E)>;
  using H = function<E(E, E)>;

private:
  F operation; // 区間に対する処理
  G affecter;  // 作用させる関数
  H merger;    // 作用素をマージ
  T et;        // 単位元
  E ee;
  vector<T> data;
  vector<E> lazy;
  size_t len, height; // 管理している要素数、高さ

  void init(int n_) {
    len = 1;
    height = 0;
    while (len < n_)
      len *= 2, height++;
    data.resize(2 * len, et);
    lazy.resize(2 * len, ee);
  }
  void eval(int k) {
    if (lazy[k] == ee)
      return;
    lazy[2 * k] = merger(lazy[2 * k], lazy[k]);
    lazy[2 * k + 1] = merger(lazy[2 * k + 1], lazy[k]);
    data[k] = affecter(data[k], lazy[k]);
    lazy[k] = ee;
  }
  inline void eval_from_root(int k) {
    // 根からkまで伝播
    for (int i = height; i > 0; i--)
      eval(k >> i);
  }
  inline T reflect(int k) {
    return lazy[k] == ee ? data[k] : affecter(data[k], lazy[k]);
  }
  inline void recalc(int k) {
    while (k /= 2)
      data[k] = operation(reflect(2 * k), reflect(2 * k + 1));
  }

public:
  LazySegmentTree(size_t N, T et, E ee, F operation, G affecter, H merger)
      : et(et), ee(ee), operation(operation), affecter(affecter),
        merger(merger) {
    init(N);
  }

  template <typename Ite>
  LazySegmentTree(size_t N, T et, E ee, F operation, G affecter, H merger,
                  Ite start, Ite end)
      : et(et), ee(ee), operation(operation), affecter(affecter),
        merger(merger) {
    init(N);
    build(start, end);
  }
  template <typename Ite> void build(Ite start, Ite end) {
    for (auto i = start; i < end; i++)
      data[i - start + len] = *i;
    for (int i = len - 1; i > 0; i--)
      data[i] = operation(data[2 * i], data[2 * i + 1]);
  }
  void update(size_t a, size_t b, E x) {
    // [a,b)
    if (a >= b)
      return;
    eval_from_root(a += len);
    eval_from_root(b += len - 1);
    for (int l = a, r = b + 1; l < r; l /= 2, r /= 2) {
      if (l % 2) {
        lazy[l] = merger(lazy[l], x);
        l++;
      }
      if (r % 2) {
        r--;
        lazy[r] = merger(lazy[r], x);
      }
    }
    recalc(a);
    recalc(b);
  }
  T query(size_t a, size_t b) {
    // [a,b)の処理
    if (a >= b)
      return et;
    eval_from_root(a += len);
    eval_from_root(b += len - 1);
    T vl = et, vr = et;
    for (int l = a, r = b + 1; l < r; l /= 2, r /= 2) {
      if (l % 2)
        vl = operation(vl, reflect(l++));
      if (r % 2)
        vr = operation(reflect(--r), vr);
    }
    return operation(vl, vr);
  }
  void set_val(size_t a, T x) {
    eval_from_root(a += len);
    data[a] = x;
    lazy[a] = ee;
    recalc(a);
  }
  void print() {
    for (auto i : data) {
      cout << i.first << " ";
    }
    cout << endl;
    for (auto i : lazy) {
      cout << i << " ";
    }
    cout << endl;
  }
};

#include <cassert>
#include <cstdint>
#include <iostream>
#include <istream>
#include <ostream>

namespace mod {
using u64 = uint_fast64_t;
using u128 = __uint128_t;
template <u64 MOD> class modInt {

private:
  u64 _a;

public:
  constexpr modInt(const long long x = 0) : _a(((x % MOD) + MOD) % MOD) {}
  constexpr inline u64 value() const { return _a; }
  constexpr modInt pow(u64 p) const {
    if (p == 0)
      return modInt(1);
    if (p % 2 == 0) {
      modInt d = pow(p / 2);
      return d * d;
    } else {
      return *this * pow(p - 1);
    }
  }
  constexpr modInt inverse() const { return pow(MOD - 2); }
  constexpr modInt &operator+=(const modInt x) {
    _a += x.value();
    if (_a >= MOD) {
      _a -= MOD;
    }
    return *this;
  }
  constexpr modInt &operator-=(const modInt x) {
    if (_a < x.value()) {
      _a += MOD;
    }
    _a -= x.value();
    return *this;
  }
  constexpr modInt &operator*=(const modInt x) {
    u128 a = _a;
    a *= x.value();
    a %= MOD;
    _a = a;
    return *this;
  }
  constexpr modInt &operator/=(const modInt x) {
    assert(x.value() != 0);
    *this *= x.inverse();
    return *this;
  }
  constexpr modInt operator++() { return *this += modInt(1); }
  constexpr modInt operator--() { return *this -= modInt(1); }
};
template <u64 MOD>
constexpr modInt<MOD> operator+(const modInt<MOD> lha, const modInt<MOD> rha) {
  return modInt<MOD>(lha) += rha;
}
template <u64 MOD>
constexpr modInt<MOD> operator-(const modInt<MOD> lha, const modInt<MOD> rha) {
  return modInt<MOD>(lha) -= rha;
}
template <u64 MOD>
constexpr modInt<MOD> operator*(const modInt<MOD> lha, const modInt<MOD> rha) {
  return modInt<MOD>(lha) *= rha;
}
template <u64 MOD>
constexpr modInt<MOD> operator/(const modInt<MOD> lha, const modInt<MOD> rha) {
  return modInt<MOD>(lha) /= rha;
}
template <u64 MOD>
constexpr modInt<MOD> operator==(const modInt<MOD> lha, const modInt<MOD> rha) {
  return lha.value() == rha.value();
}
template <u64 MOD>
constexpr modInt<MOD> operator!=(const modInt<MOD> lha, const modInt<MOD> rha) {
  return !(lha.value() == rha.value());
}
template <u64 MOD>
std::ostream &operator<<(std::ostream &stream, const modInt<MOD> x) {
  stream << x.value();
  return stream;
}
template <u64 MOD>
std::istream &operator>>(std::istream &stream, modInt<MOD> &x) {
  u64 a;
  stream >> a;
  x = modInt<MOD>(a);
  return stream;
}
} // namespace mod

using ll = long long;
using modint = mod::modInt<998244353>;
using pmi = pair<modint, int>;

int log2(int a) {
  int ret = 0;
  int now = 1;
  while (now < a) {
    ret++;
    now *= 2;
  }
  return ret;
}

int main() {
  int n, q;
  cin >> n >> q;
  vector<modint> p10(n + 1, 1);
  for (int i = 0; i < n; i++)
    p10[i + 1] = p10[i] * modint(10);
  vector<vector<pmi>> table(10, vector<pmi>(n + 1));
  for (int d = 1; d < 10; d++) {
    auto &vs = table[d];
    vs[0] = pmi(0, 0);
    for (int i = 0; i < n; i++)
      vs[i + 1] = pmi(vs[i].first * modint(10) + modint(d), i + 1);
  }
  vector<pmi> a(n, pmi(modint(1), 1));
  auto st = LazySegmentTree<pmi, int>(
      n, pmi(0, 0), -1,
      [&](pmi a, pmi b) -> pmi {
        return pmi((a.first * p10[b.second] + b.first), a.second + b.second);
      },
      [&](pmi a, int b) -> pmi { return b < 0 ? a : table[b][a.second]; },
      [&](int a, int b) -> int { return b; }, a.begin(), a.end());
  for (int i = 0; i < q; i++) {
    int l, r, d;
    cin >> l >> r >> d;
    st.update(l - 1, r, d);
    cout << st.query(0, n).first << endl;
  }
}


Measured memory_bytes: 48980