#include<bits/stdc++.h>
using namespace std;
#define all(x) x.begin(), x.end()
typedef vector <int> vi;
typedef pair<int,int> ii;
typedef long long ll;
typedef long double ld;
const int mod = 998244353;
const ll inf = 3e18 + 5;
int add(int a, int b) { return (a += b) < mod ? a : a - mod; }
int mul(int a, int b) { return 1LL * a * b % mod; }
int sub(int a, int b) { return (a -= b) < 0 ? a + mod : a; }
int fpow(int a, int b){
  if(b == 0) return 1;
  int re = fpow(a, b / 2);
  if(b % 2 == 1) return mul(a, mul(re, re));
  return mul(re, re);
}
int inv(int x) {
  return fpow(x, mod - 2);
}

int inv9, pow10[200500];

template <typename T>
struct lazysegtree {

  struct node {
    int l, r; // range [l, r] koji obuhvaca taj node
    T val; // agregirajuca vrijednost

    // tu dodaj varijable za lazy propagaciju
    T num = -1;

    int lenght() { return r - l + 1; }
    T calc(int n) {
      int R = n - l - 1;
      int L = n - r - 1;
      T ret = sub(pow10[R - L + 1], 1);
      ret = mul(ret, inv9);
      ret = mul(ret, pow10[l]);
      ret = mul(ret, num);
      return ret;
    }
  };


  int n;
  vector <node> seg;
  vector <T> arr; // baza segtreea

  lazysegtree(int _n, vector<T> _arr) : seg(4 * _n + 1) {
    n = _n;
    arr = _arr;
    Build(1, 0, n - 1);
  }

  // obnovi rjesenje za segment od node-a seg[ind]
  void Recalculate(int ind) {
    assert(ind * 2 < seg.size());
    node& leftChild = seg[ind * 2];
    assert(ind * 2 + 1 < seg.size());
    node& rightChild = seg[ind * 2 + 1];
    T L = leftChild.val;
    if(leftChild.num != -1) {
      L = leftChild.calc(n);
    }
    T R = rightChild.val;
    if(rightChild.num != -1) {
      R = rightChild.calc(n);
    }
    seg[ind].val = add(L, R);
  }

  // pushaj informacije sa seg[ind] na djecu
  void Push(int ind) {
    assert(ind * 2 < seg.size());
    node& leftChild = seg[ind * 2];
    assert(ind * 2 + 1 < seg.size());
    node& rightChild = seg[ind * 2 + 1];
    // ne zaboravi resetat varijable propagacije od seg[ind] na kraju
    if(seg[ind].num != -1) {
      leftChild.num = rightChild.num = seg[ind].num;
    }
    seg[ind].num = -1;
  }

  void Build(int ind, int l, int r) {
    seg[ind].l = l;
    seg[ind].r = r;
    if(l == r) {
      seg[ind].val = arr[l];
      return;
    }
    int mid = (l + r) / 2;
    Build(ind * 2, l, mid);
    Build(ind * 2 + 1, mid + 1, r);
    Recalculate(ind);
  }

  void Upd(int l, int r, T val) {
    assert(r < n); // 0-indeksirano
    Upd(l, r, val, 0, n - 1, 1);
  }

  // updateaj [l, r] (0-indeksirano) sa vrijednoscu val 
  void Upd(int l, int r, T val, int cl, int cr, int ind) {
    if(cl > r || cr < l) return;
    if(cl >= l && cr <= r) {
      seg[ind].num = val;
      return;
    }
    Push(ind);
    int mid = (cl + cr) / 2;
    Upd(l, r, val, cl, mid, ind * 2);
    Upd(l, r, val, mid + 1, cr, ind * 2 + 1);
    Recalculate(ind);
  }

  T Get(int l, int r) {
    assert(r < n); // mora bit 0-indeksirano
    return Get(l, r, 0, n - 1, 1);
  }

  // rjesenje za [l, r] (0-indeksirano)
  T Get(int l, int r, int cl, int cr, int ind) {
    if(cl > r || cr < l) return 0;
    if(cl >= l && cr <= r) {
      // implementiraj sam
      if(seg[ind].num != -1) {
        return seg[ind].calc(n);
      } else {
        return seg[ind].val;
      }
    }
    Push(ind);
    int mid = (cl + cr) / 2;
    T L = Get(l, r, cl, mid, ind * 2);
    T R = Get(l, r, mid + 1, cr, ind * 2 + 1);
    Recalculate(ind);
    return add(L, R);
  } 
};

int main() {
  ios_base::sync_with_stdio(false); cin.tie(0);
  #ifdef LOCAL
  freopen("input.txt", "r", stdin);
  freopen("output.txt", "w", stdout);
  #endif

  inv9 = inv(9);
  pow10[0] = 1;
  for(int i = 1; i <= 200001; i++) {
    pow10[i] = mul(pow10[i - 1], 10);
  }
  int n, q;
  cin >> n >> q;
  vi a(n);
  lazysegtree<int> seg(n, a);
  seg.Upd(0, n - 1, 1);
  while(q--) {
    int l, r, d;
    cin >> l >> r >> d;
    seg.Upd(n - r, n - l, d);
    int val = seg.Get(0, n - 1);
    cout << val << "\n";
  }
}

Measured memory_bytes: 18772