Problem p02538 (C++) — buggy submission, verdict: Runtime Error

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

template <typename T> struct Z_p {
  using Type = typename decay<decltype(T::value)>::type;
  static vector<Type> mod_inv;
  constexpr Z_p() : value() {}
  template <typename U> Z_p(const U &x) { value = normalize(x); }
  template <typename U> static Type normalize(const U &x) {
    Type v;
    if (-mod() <= x && x < mod())
      v = static_cast<Type>(x);
    else
      v = static_cast<Type>(x % mod());
    if (v < 0)
      v += mod();
    return v;
  }
  const Type &operator()() const { return value; }
  template <typename U> explicit operator U() const {
    return static_cast<U>(value);
  }
  constexpr static Type mod() { return T::value; }
  Z_p &operator+=(const Z_p &otr) {
    if ((value += otr.value) >= mod())
      value -= mod();
    return *this;
  }
  Z_p &operator-=(const Z_p &otr) {
    if ((value -= otr.value) < 0)
      value += mod();
    return *this;
  }
  template <typename U> Z_p &operator+=(const U &otr) {
    return *this += Z_p(otr);
  }
  template <typename U> Z_p &operator-=(const U &otr) {
    return *this -= Z_p(otr);
  }
  Z_p &operator++() { return *this += 1; }
  Z_p &operator--() { return *this -= 1; }
  Z_p operator++(int) {
    Z_p result(*this);
    *this += 1;
    return result;
  }
  Z_p operator--(int) {
    Z_p result(*this);
    *this -= 1;
    return result;
  }
  Z_p operator-() const { return Z_p(-value); }
  template <typename U = T>
  typename enable_if<is_same<typename Z_p<U>::Type, int>::value, Z_p>::type &
  operator*=(const Z_p &rhs) {
#ifdef _WIN32
    uint64_t x = static_cast<int64_t>(value) * static_cast<int64_t>(rhs.value);
    uint32_t xh = static_cast<uint32_t>(x >> 32), xl = static_cast<uint32_t>(x),
             d, m;
    asm("divl %4; \\n\\t" : "=a"(d), "=d"(m) : "d"(xh), "a"(xl), "r"(mod()));
    value = m;
#else
    value = normalize(static_cast<int64_t>(value) *
                      static_cast<int64_t>(rhs.value));
#endif
    return *this;
  }
  template <typename U = T>
  typename enable_if<is_same<typename Z_p<U>::Type, int64_t>::value, Z_p>::type
      &
      operator*=(const Z_p &rhs) {
    int64_t q = static_cast<int64_t>(static_cast<long double>(value) *
                                     rhs.value / mod());
    value = normalize(value * rhs.value - q * mod());
    return *this;
  }
  template <typename U = T>
  typename enable_if<!is_integral<typename Z_p<U>::Type>::value, Z_p>::type &
  operator*=(const Z_p &rhs) {
    value = normalize(value * rhs.value);
    return *this;
  }
  Z_p operator^(long long e) const {
    Z_p b = *this, res = 1;
    if (e < 0)
      b = 1 / b, e = -e;
    for (; e; b *= b, e >>= 1)
      if (e & 1)
        res *= b;
    return res;
  }
  Z_p &operator^=(const long long &e) { return *this = *this ^ e; }
  Z_p &operator/=(const Z_p &otr) {
    Type a = otr.value, m = mod(), u = 0, v = 1;
    if (a < int(mod_inv.size()))
      return *this *= mod_inv[a];
    while (a) {
      Type t = m / a;
      m -= t * a;
      swap(a, m);
      u -= t * v;
      swap(u, v);
    }
    assert(m == 1);
    return *this *= u;
  }
  template <typename U> friend const Z_p<U> &abs(const Z_p<U> &v) { return v; }
  template <typename U>
  friend bool operator==(const Z_p<U> &lhs, const Z_p<U> &rhs);
  template <typename U>
  friend bool operator<(const Z_p<U> &lhs, const Z_p<U> &rhs);
  template <typename U> friend istream &operator>>(istream &in, Z_p<U> &number);
  Type value;
};
template <typename T> bool operator==(const Z_p<T> &lhs, const Z_p<T> &rhs) {
  return lhs.value == rhs.value;
}
template <typename T, typename U,
          typename enable_if<is_integral<U>::value>::type * = nullptr>
bool operator==(const Z_p<T> &lhs, U rhs) {
  return lhs == Z_p<T>(rhs);
}
template <typename T, typename U,
          typename enable_if<is_integral<U>::value>::type * = nullptr>
bool operator==(U lhs, const Z_p<T> &rhs) {
  return Z_p<T>(lhs) == rhs;
}
template <typename T> bool operator!=(const Z_p<T> &lhs, const Z_p<T> &rhs) {
  return !(lhs == rhs);
}
template <typename T, typename U,
          typename enable_if<is_integral<U>::value>::type * = nullptr>
bool operator!=(const Z_p<T> &lhs, U rhs) {
  return !(lhs == rhs);
}
template <typename T, typename U,
          typename enable_if<is_integral<U>::value>::type * = nullptr>
bool operator!=(U lhs, const Z_p<T> &rhs) {
  return !(lhs == rhs);
}
template <typename T> bool operator<(const Z_p<T> &lhs, const Z_p<T> &rhs) {
  return lhs.value < rhs.value;
}
template <typename T> Z_p<T> operator+(const Z_p<T> &lhs, const Z_p<T> &rhs) {
  return Z_p<T>(lhs) += rhs;
}
template <typename T, typename U,
          typename enable_if<is_integral<U>::value>::type * = nullptr>
Z_p<T> operator+(const Z_p<T> &lhs, U rhs) {
  return Z_p<T>(lhs) += rhs;
}
template <typename T, typename U,
          typename enable_if<is_integral<U>::value>::type * = nullptr>
Z_p<T> operator+(U lhs, const Z_p<T> &rhs) {
  return Z_p<T>(lhs) += rhs;
}
template <typename T> Z_p<T> operator-(const Z_p<T> &lhs, const Z_p<T> &rhs) {
  return Z_p<T>(lhs) -= rhs;
}
template <typename T, typename U,
          typename enable_if<is_integral<U>::value>::type * = nullptr>
Z_p<T> operator-(const Z_p<T> &lhs, U rhs) {
  return Z_p<T>(lhs) -= rhs;
}
template <typename T, typename U,
          typename enable_if<is_integral<U>::value>::type * = nullptr>
Z_p<T> operator-(U lhs, const Z_p<T> &rhs) {
  return Z_p<T>(lhs) -= rhs;
}
template <typename T> Z_p<T> operator*(const Z_p<T> &lhs, const Z_p<T> &rhs) {
  return Z_p<T>(lhs) *= rhs;
}
template <typename T, typename U,
          typename enable_if<is_integral<U>::value>::type * = nullptr>
Z_p<T> operator*(const Z_p<T> &lhs, U rhs) {
  return Z_p<T>(lhs) *= rhs;
}
template <typename T, typename U,
          typename enable_if<is_integral<U>::value>::type * = nullptr>
Z_p<T> operator*(U lhs, const Z_p<T> &rhs) {
  return Z_p<T>(lhs) *= rhs;
}
template <typename T> Z_p<T> operator/(const Z_p<T> &lhs, const Z_p<T> &rhs) {
  return Z_p<T>(lhs) /= rhs;
}
template <typename T, typename U,
          typename enable_if<is_integral<U>::value>::type * = nullptr>
Z_p<T> operator/(const Z_p<T> &lhs, U rhs) {
  return Z_p<T>(lhs) /= rhs;
}
template <typename T, typename U,
          typename enable_if<is_integral<U>::value>::type * = nullptr>
Z_p<T> operator/(U lhs, const Z_p<T> &rhs) {
  return Z_p<T>(lhs) /= rhs;
}
template <typename T> istream &operator>>(istream &in, Z_p<T> &number) {
  typename common_type<typename Z_p<T>::Type, int64_t>::type x;
  in >> x;
  number.value = Z_p<T>::normalize(x);
  return in;
}
template <typename T> ostream &operator<<(ostream &out, const Z_p<T> &number) {
  return out << number();
}

/*
using ModType = int;
struct VarMod{ static ModType value; };
ModType VarMod::value;
ModType &mod = VarMod::value;
using Zp = Z_p<VarMod>;
*/

constexpr int mod = (119 << 23) + 1;
using Zp = Z_p<integral_constant<decay<decltype(mod)>::type, mod>>;

template <typename T> vector<typename Z_p<T>::Type> Z_p<T>::mod_inv;
template <typename T = integral_constant<decay<decltype(mod)>::type, mod>>
void precalc_inverse(size_t SZ) {
  auto &inv = Z_p<T>::mod_inv;
  if (inv.empty())
    inv.assign(2, 1);
  for (; inv.size() <= SZ;)
    inv.push_back(
        (mod - 1LL * mod / int(inv.size()) * inv[mod % int(inv.size())] % mod) %
        mod);
}

template <typename Q, typename L> struct lazy_segment_tree {
  lazy_segment_tree() : lazy_segment_tree(0) {}
  lazy_segment_tree(int n) : lazy_segment_tree(vector<Q>(n)) {}
  lazy_segment_tree(const vector<Q> &v) : n((int)v.size()) { // O(n)
    log = __lg(n + 1) + 1;
    size = 1 << log;
    val = vector<Q>(size << 1);
    lazy = vector<L>(size);
    copy(v.begin(), v.end(), val.begin() + size);
    for (int i = 1; i < size; ++i) {
      int h = log - __lg(i);
      lazy[i] = {(i << h) - size, (i + 1 << h) - size};
    }
    for (int i = size - 1; i >= 1; --i)
      update(i);
  }
  Q query(int p) { // O(log n)
    assert(0 <= p && p < n);
    p += size;
    for (int i = log; i >= 1; --i)
      push(p >> i);
    return val[p];
  }
  Q query(int l, int r) { // O(log n)
    assert(0 <= l && l <= r && r <= n);
    if (l == r)
      return {};
    l += size, r += size;
    for (int i = log; i >= 1; --i) {
      if (((l >> i) << i) != l)
        push(l >> i);
      if (((r >> i) << i) != r)
        push(r >> i);
    }
    Q sml{}, smr{};
    for (; l < r; l >>= 1, r >>= 1) {
      if (l & 1)
        sml = sml + val[l++];
      if (r & 1)
        smr = val[--r] + smr;
    }
    return sml + smr;
  }
  Q query_all() { return val[1]; } // O(1)
  void update(int p, Q x) {        // O(log n)
    assert(0 <= p && p < n);
    p += size;
    for (int i = log; i >= 1; --i)
      push(p >> i);
    val[p] = x;
    for (int i = 1; i <= log; ++i)
      update(p >> i);
  }
  void update(int p, L f) { // O(log n)
    assert(0 <= p && p < n);
    p += size;
    for (int i = log; i >= 1; --i)
      push(p >> i);
    val[p] = f + val[p];
    for (int i = 1; i <= log; ++i)
      update(p >> i);
  }
  void update(int l, int r, L f) { // O(log n)
    assert(0 <= l && l <= r && r <= n);
    if (l == r)
      return;
    l += size, r += size;
    for (int i = log; i >= 1; --i) {
      if (((l >> i) << i) != l)
        push(l >> i);
      if (((r >> i) << i) != r)
        push(r - 1 >> i);
    }
    int l2 = l, r2 = r;
    for (; l < r; l >>= 1, r >>= 1) {
      if (l & 1)
        apply(l++, f);
      if (r & 1)
        apply(--r, f);
    }
    l = l2, r = r2;
    for (int i = 1; i <= log; ++i) {
      if (((l >> i) << i) != l)
        update(l >> i);
      if (((r >> i) << i) != r)
        update((r - 1) >> i);
    }
  }
  template <typename G> int partition_point_pref(int l, G g) { // O(log n)
    assert(0 <= l && l <= n), assert(g({}));
    if (l == n)
      return n;
    l += size;
    for (int i = log; i >= 1; ++i)
      push(l >> i);
    Q sm{};
    do {
      while (~l & 1)
        l >>= 1;
      if (!g(sm + val[l])) {
        while (l < size) {
          push(l);
          l = l << 1;
          if (g(sm + val[l]))
            sm = sm + val[l++];
        }
        return l - size;
      }
      sm = sm + val[l];
      ++l;
    } while ((l & -l) != l);
    return n;
  } // f(sum[l, r)) is T, T, ..., T, F, F, ..., F, returns max r with T
  template <typename G> int partition_point_suff(int r, G g) { // O(log n)
    assert(0 <= r && r <= n), assert(g({}));
    if (r == 0)
      return 0;
    r += size;
    for (int i = log; i >= 1; --i)
      push(r - 1 >> i);
    Q sm{};
    do {
      --r;
      while (r > 1 && r & 1)
        r >>= 1;
      if (!g(val[r] + sm)) {
        while (r < size) {
          push(r);
          r = r << 1 | 1;
          if (g(val[r] + sm))
            sm = val[r--] + sm;
        }
        return r + 1 - size;
      }
      sm = val[r] + sm;
    } while ((r & -r) != r);
    return 0;
  } // f(sum[l, r)) is F, F, ..., F, T, T, ..., T, returns min l with T
  int n, size, log;
  vector<Q> val;
  vector<L> lazy;
  void update(int i) { val[i] = val[i << 1] + val[i << 1 | 1]; }
  void apply(int i, L f) {
    val[i] = f + val[i];
    if (i < size)
      lazy[i] = f + lazy[i];
  }
  void push(int i) {
    apply(i << 1, lazy[i]), apply(i << 1 | 1, lazy[i]);
    int h = log - __lg(i);
    lazy[i] = {(i << h) - size, (i + 1 << h) - size};
  }
};

int n;
array<Zp, 400100> p, pref;

int main() {
  cin.tie(0)->sync_with_stdio(0);
  cin.exceptions(ios::badbit | ios::failbit);
  int qn;
  cin >> n >> qn;
  p[0] = 1;
  for (auto i = 0; i <= 400010; ++i) {
    p[i + 1] = p[i] * 10;
    pref[i + 1] = pref[i] + p[i];
  }
  struct Q { // Monoid (Query type) / Default constructor yields the identity
    Zp val = 0;
    int len = 0;
    Q operator+(const Q &x) const {
      return {val * p[x.len] + x.val, len + x.len};
    } // Monoid operator, always merges adjacent intervals
  };
  struct L { // Semigroup (Lazy type) / call L(l, r) for initial lazy type for
             // interval [l, r)
    int set_to = 0;
    L() {}
    L(int l, int r) {}
    L(int a) : set_to(a) {}
    L operator+(const L &x) const {
      return set_to ? *this : x;
    } // Monoid operator, always applies superset to subset
    Q operator+(const Q &x) const {
      return set_to ? Q{set_to * pref[x.len], x.len} : x;
    } // Semigroup action of L on Q, always applies superset to subset
  };
  vector<Q> t(n);
  for (auto i = 0; i < n; ++i) {
    t[i] = {1, 1};
  }
  lazy_segment_tree<Q, L> seg(t);
  for (auto rep = 0; rep < qn; ++rep) {
    int l, r, d;
    cin >> l >> r >> d, --l;
    seg.update(l, r, {d});
    cout << seg.query_all().val << "\\n";
  }
  return 0;
}

/*

*/

////////////////////////////////////////////////////////////////////////////////////////
//                                                                                    //
//                                   Coded by Aeren //
//                                                                                    //
////////////////////////////////////////////////////////////////////////////////////////

Error: WA

Fixed submission:

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

template <typename T> struct Z_p {
  using Type = typename decay<decltype(T::value)>::type;
  static vector<Type> mod_inv;
  constexpr Z_p() : value() {}
  template <typename U> Z_p(const U &x) { value = normalize(x); }
  template <typename U> static Type normalize(const U &x) {
    Type v;
    if (-mod() <= x && x < mod())
      v = static_cast<Type>(x);
    else
      v = static_cast<Type>(x % mod());
    if (v < 0)
      v += mod();
    return v;
  }
  const Type &operator()() const { return value; }
  template <typename U> explicit operator U() const {
    return static_cast<U>(value);
  }
  constexpr static Type mod() { return T::value; }
  Z_p &operator+=(const Z_p &otr) {
    if ((value += otr.value) >= mod())
      value -= mod();
    return *this;
  }
  Z_p &operator-=(const Z_p &otr) {
    if ((value -= otr.value) < 0)
      value += mod();
    return *this;
  }
  template <typename U> Z_p &operator+=(const U &otr) {
    return *this += Z_p(otr);
  }
  template <typename U> Z_p &operator-=(const U &otr) {
    return *this -= Z_p(otr);
  }
  Z_p &operator++() { return *this += 1; }
  Z_p &operator--() { return *this -= 1; }
  Z_p operator++(int) {
    Z_p result(*this);
    *this += 1;
    return result;
  }
  Z_p operator--(int) {
    Z_p result(*this);
    *this -= 1;
    return result;
  }
  Z_p operator-() const { return Z_p(-value); }
  template <typename U = T>
  typename enable_if<is_same<typename Z_p<U>::Type, int>::value, Z_p>::type &
  operator*=(const Z_p &rhs) {
#ifdef _WIN32
    uint64_t x = static_cast<int64_t>(value) * static_cast<int64_t>(rhs.value);
    uint32_t xh = static_cast<uint32_t>(x >> 32), xl = static_cast<uint32_t>(x),
             d, m;
    asm("divl %4; \\n\\t" : "=a"(d), "=d"(m) : "d"(xh), "a"(xl), "r"(mod()));
    value = m;
#else
    value = normalize(static_cast<int64_t>(value) *
                      static_cast<int64_t>(rhs.value));
#endif
    return *this;
  }
  template <typename U = T>
  typename enable_if<is_same<typename Z_p<U>::Type, int64_t>::value, Z_p>::type
      &
      operator*=(const Z_p &rhs) {
    int64_t q = static_cast<int64_t>(static_cast<long double>(value) *
                                     rhs.value / mod());
    value = normalize(value * rhs.value - q * mod());
    return *this;
  }
  template <typename U = T>
  typename enable_if<!is_integral<typename Z_p<U>::Type>::value, Z_p>::type &
  operator*=(const Z_p &rhs) {
    value = normalize(value * rhs.value);
    return *this;
  }
  Z_p operator^(long long e) const {
    Z_p b = *this, res = 1;
    if (e < 0)
      b = 1 / b, e = -e;
    for (; e; b *= b, e >>= 1)
      if (e & 1)
        res *= b;
    return res;
  }
  Z_p &operator^=(const long long &e) { return *this = *this ^ e; }
  Z_p &operator/=(const Z_p &otr) {
    Type a = otr.value, m = mod(), u = 0, v = 1;
    if (a < int(mod_inv.size()))
      return *this *= mod_inv[a];
    while (a) {
      Type t = m / a;
      m -= t * a;
      swap(a, m);
      u -= t * v;
      swap(u, v);
    }
    assert(m == 1);
    return *this *= u;
  }
  template <typename U> friend const Z_p<U> &abs(const Z_p<U> &v) { return v; }
  template <typename U>
  friend bool operator==(const Z_p<U> &lhs, const Z_p<U> &rhs);
  template <typename U>
  friend bool operator<(const Z_p<U> &lhs, const Z_p<U> &rhs);
  template <typename U> friend istream &operator>>(istream &in, Z_p<U> &number);
  Type value;
};
template <typename T> bool operator==(const Z_p<T> &lhs, const Z_p<T> &rhs) {
  return lhs.value == rhs.value;
}
template <typename T, typename U,
          typename enable_if<is_integral<U>::value>::type * = nullptr>
bool operator==(const Z_p<T> &lhs, U rhs) {
  return lhs == Z_p<T>(rhs);
}
template <typename T, typename U,
          typename enable_if<is_integral<U>::value>::type * = nullptr>
bool operator==(U lhs, const Z_p<T> &rhs) {
  return Z_p<T>(lhs) == rhs;
}
template <typename T> bool operator!=(const Z_p<T> &lhs, const Z_p<T> &rhs) {
  return !(lhs == rhs);
}
template <typename T, typename U,
          typename enable_if<is_integral<U>::value>::type * = nullptr>
bool operator!=(const Z_p<T> &lhs, U rhs) {
  return !(lhs == rhs);
}
template <typename T, typename U,
          typename enable_if<is_integral<U>::value>::type * = nullptr>
bool operator!=(U lhs, const Z_p<T> &rhs) {
  return !(lhs == rhs);
}
template <typename T> bool operator<(const Z_p<T> &lhs, const Z_p<T> &rhs) {
  return lhs.value < rhs.value;
}
template <typename T> Z_p<T> operator+(const Z_p<T> &lhs, const Z_p<T> &rhs) {
  return Z_p<T>(lhs) += rhs;
}
template <typename T, typename U,
          typename enable_if<is_integral<U>::value>::type * = nullptr>
Z_p<T> operator+(const Z_p<T> &lhs, U rhs) {
  return Z_p<T>(lhs) += rhs;
}
template <typename T, typename U,
          typename enable_if<is_integral<U>::value>::type * = nullptr>
Z_p<T> operator+(U lhs, const Z_p<T> &rhs) {
  return Z_p<T>(lhs) += rhs;
}
template <typename T> Z_p<T> operator-(const Z_p<T> &lhs, const Z_p<T> &rhs) {
  return Z_p<T>(lhs) -= rhs;
}
template <typename T, typename U,
          typename enable_if<is_integral<U>::value>::type * = nullptr>
Z_p<T> operator-(const Z_p<T> &lhs, U rhs) {
  return Z_p<T>(lhs) -= rhs;
}
template <typename T, typename U,
          typename enable_if<is_integral<U>::value>::type * = nullptr>
Z_p<T> operator-(U lhs, const Z_p<T> &rhs) {
  return Z_p<T>(lhs) -= rhs;
}
template <typename T> Z_p<T> operator*(const Z_p<T> &lhs, const Z_p<T> &rhs) {
  return Z_p<T>(lhs) *= rhs;
}
template <typename T, typename U,
          typename enable_if<is_integral<U>::value>::type * = nullptr>
Z_p<T> operator*(const Z_p<T> &lhs, U rhs) {
  return Z_p<T>(lhs) *= rhs;
}
template <typename T, typename U,
          typename enable_if<is_integral<U>::value>::type * = nullptr>
Z_p<T> operator*(U lhs, const Z_p<T> &rhs) {
  return Z_p<T>(lhs) *= rhs;
}
template <typename T> Z_p<T> operator/(const Z_p<T> &lhs, const Z_p<T> &rhs) {
  return Z_p<T>(lhs) /= rhs;
}
template <typename T, typename U,
          typename enable_if<is_integral<U>::value>::type * = nullptr>
Z_p<T> operator/(const Z_p<T> &lhs, U rhs) {
  return Z_p<T>(lhs) /= rhs;
}
template <typename T, typename U,
          typename enable_if<is_integral<U>::value>::type * = nullptr>
Z_p<T> operator/(U lhs, const Z_p<T> &rhs) {
  return Z_p<T>(lhs) /= rhs;
}
template <typename T> istream &operator>>(istream &in, Z_p<T> &number) {
  typename common_type<typename Z_p<T>::Type, int64_t>::type x;
  in >> x;
  number.value = Z_p<T>::normalize(x);
  return in;
}
template <typename T> ostream &operator<<(ostream &out, const Z_p<T> &number) {
  return out << number();
}

/*
using ModType = int;
struct VarMod{ static ModType value; };
ModType VarMod::value;
ModType &mod = VarMod::value;
using Zp = Z_p<VarMod>;
*/

constexpr int mod = (119 << 23) + 1;
using Zp = Z_p<integral_constant<decay<decltype(mod)>::type, mod>>;

template <typename T> vector<typename Z_p<T>::Type> Z_p<T>::mod_inv;
template <typename T = integral_constant<decay<decltype(mod)>::type, mod>>
void precalc_inverse(size_t SZ) {
  auto &inv = Z_p<T>::mod_inv;
  if (inv.empty())
    inv.assign(2, 1);
  for (; inv.size() <= SZ;)
    inv.push_back(
        (mod - 1LL * mod / int(inv.size()) * inv[mod % int(inv.size())] % mod) %
        mod);
}

template <typename Q, typename L> struct lazy_segment_tree {
  lazy_segment_tree() : lazy_segment_tree(0) {}
  lazy_segment_tree(int n) : lazy_segment_tree(vector<Q>(n)) {}
  lazy_segment_tree(const vector<Q> &v) : n((int)v.size()) { // O(n)
    log = __lg(n + 1) + 1;
    size = 1 << log;
    val = vector<Q>(size << 1);
    lazy = vector<L>(size);
    copy(v.begin(), v.end(), val.begin() + size);
    for (int i = 1; i < size; ++i) {
      int h = log - __lg(i);
      lazy[i] = {(i << h) - size, (i + 1 << h) - size};
    }
    for (int i = size - 1; i >= 1; --i)
      update(i);
  }
  Q query(int p) { // O(log n)
    assert(0 <= p && p < n);
    p += size;
    for (int i = log; i >= 1; --i)
      push(p >> i);
    return val[p];
  }
  Q query(int l, int r) { // O(log n)
    assert(0 <= l && l <= r && r <= n);
    if (l == r)
      return {};
    l += size, r += size;
    for (int i = log; i >= 1; --i) {
      if (((l >> i) << i) != l)
        push(l >> i);
      if (((r >> i) << i) != r)
        push(r >> i);
    }
    Q sml{}, smr{};
    for (; l < r; l >>= 1, r >>= 1) {
      if (l & 1)
        sml = sml + val[l++];
      if (r & 1)
        smr = val[--r] + smr;
    }
    return sml + smr;
  }
  Q query_all() { return val[1]; } // O(1)
  void update(int p, Q x) {        // O(log n)
    assert(0 <= p && p < n);
    p += size;
    for (int i = log; i >= 1; --i)
      push(p >> i);
    val[p] = x;
    for (int i = 1; i <= log; ++i)
      update(p >> i);
  }
  void update(int p, L f) { // O(log n)
    assert(0 <= p && p < n);
    p += size;
    for (int i = log; i >= 1; --i)
      push(p >> i);
    val[p] = f + val[p];
    for (int i = 1; i <= log; ++i)
      update(p >> i);
  }
  void update(int l, int r, L f) { // O(log n)
    assert(0 <= l && l <= r && r <= n);
    if (l == r)
      return;
    l += size, r += size;
    for (int i = log; i >= 1; --i) {
      if (((l >> i) << i) != l)
        push(l >> i);
      if (((r >> i) << i) != r)
        push(r - 1 >> i);
    }
    int l2 = l, r2 = r;
    for (; l < r; l >>= 1, r >>= 1) {
      if (l & 1)
        apply(l++, f);
      if (r & 1)
        apply(--r, f);
    }
    l = l2, r = r2;
    for (int i = 1; i <= log; ++i) {
      if (((l >> i) << i) != l)
        update(l >> i);
      if (((r >> i) << i) != r)
        update((r - 1) >> i);
    }
  }
  template <typename G> int partition_point_pref(int l, G g) { // O(log n)
    assert(0 <= l && l <= n), assert(g({}));
    if (l == n)
      return n;
    l += size;
    for (int i = log; i >= 1; ++i)
      push(l >> i);
    Q sm{};
    do {
      while (~l & 1)
        l >>= 1;
      if (!g(sm + val[l])) {
        while (l < size) {
          push(l);
          l = l << 1;
          if (g(sm + val[l]))
            sm = sm + val[l++];
        }
        return l - size;
      }
      sm = sm + val[l];
      ++l;
    } while ((l & -l) != l);
    return n;
  } // f(sum[l, r)) is T, T, ..., T, F, F, ..., F, returns max r with T
  template <typename G> int partition_point_suff(int r, G g) { // O(log n)
    assert(0 <= r && r <= n), assert(g({}));
    if (r == 0)
      return 0;
    r += size;
    for (int i = log; i >= 1; --i)
      push(r - 1 >> i);
    Q sm{};
    do {
      --r;
      while (r > 1 && r & 1)
        r >>= 1;
      if (!g(val[r] + sm)) {
        while (r < size) {
          push(r);
          r = r << 1 | 1;
          if (g(val[r] + sm))
            sm = val[r--] + sm;
        }
        return r + 1 - size;
      }
      sm = val[r] + sm;
    } while ((r & -r) != r);
    return 0;
  } // f(sum[l, r)) is F, F, ..., F, T, T, ..., T, returns min l with T
  int n, size, log;
  vector<Q> val;
  vector<L> lazy;
  void update(int i) { val[i] = val[i << 1] + val[i << 1 | 1]; }
  void apply(int i, L f) {
    val[i] = f + val[i];
    if (i < size)
      lazy[i] = f + lazy[i];
  }
  void push(int i) {
    apply(i << 1, lazy[i]), apply(i << 1 | 1, lazy[i]);
    int h = log - __lg(i);
    lazy[i] = {(i << h) - size, (i + 1 << h) - size};
  }
};

int n;
vector<Zp> p, pref;

int main() {
  cin.tie(0)->sync_with_stdio(0);
  cin.exceptions(ios::badbit | ios::failbit);
  int qn;
  cin >> n >> qn;
  n = 1 << __lg(n + 1);
  p.assign(n + 1, Zp(1));
  pref.assign(n + 2, Zp(0));
  for (auto i = 0; i < n; ++i) {
    p[i + 1] = p[i] * 10;
  }
  for (auto i = 1; i <= n + 1; ++i) {
    pref[i] = pref[i - 1] + p[i - 1];
  }
  struct Q { // Monoid (Query type) / Default constructor yields the identity
    Zp val = 0;
    int len = 0;
    Q operator+(const Q &x) const {
      return {val * p[x.len] + x.val, len + x.len};
    } // Monoid operator, always merges adjacent intervals
  };
  struct L { // Semigroup (Lazy type) / call L(l, r) for initial lazy type for
             // interval [l, r)
    int set_to = 0;
    L() {}
    L(int l, int r) {}
    L(int a) : set_to(a) {}
    L operator+(const L &x) const {
      return set_to ? *this : x;
    } // Monoid operator, always applies superset to subset
    Q operator+(const Q &x) const {
      return set_to ? Q{set_to * pref[x.len], x.len} : x;
    } // Semigroup action of L on Q, always applies superset to subset
  };
  vector<Q> t(n);
  for (auto i = 0; i < n; ++i) {
    t[i] = {1, 1};
  }
  lazy_segment_tree<Q, L> seg(t);
  cout << seg.query_all().val << "\\n";
  for (auto rep = 0; rep < qn; ++rep) {
    int l, r, d;
    cin >> l >> r >> d, --l;
    seg.update(l, r, {d});
    cout << seg.query_all().val << "\\n";
  }
  return 0;
}

/*

*/

////////////////////////////////////////////////////////////////////////////////////////
//                                                                                    //
//                                   Coded by Aeren //
//                                                                                    //
////////////////////////////////////////////////////////////////////////////////////////