Problem p02538 (C++)

Buggy submission (status: Time Limit Exceeded):
#include <bits/stdc++.h>
using namespace std;
#define rep(i, n) for (ll i = 0; i < n; i++)
#define repl(i, l, r) for (ll i = (l); i < (r); i++)
#define per(i, n) for (ll i = n - 1; i >= 0; i--)
#define perl(i, r, l) for (ll i = r - 1; i >= l; i--)
#define fi first
#define se second
#define pb push_back
#define ins insert
#define pqueue(x) priority_queue<x, vector<x>, greater<x>>
#define all(x) (x).begin(), (x).end()
#define CST(x) cout << fixed << setprecision(x)
#define vtpl(x, y, z) vector<tuple<x, y, z>>
#define rev(x) reverse(x);
using ll = long long;
using vl = vector<ll>;
using vvl = vector<vector<ll>>;
using pl = pair<ll, ll>;
using vpl = vector<pl>;
using vvpl = vector<vpl>;
const ll MOD = 1000000007;
const ll MOD9 = 998244353;
const int inf = 1e9 + 10;
const ll INF = 4e18;
const ll dy[9] = {0, 0, 1, -1, 1, 1, -1, -1, 0};
const ll dx[9] = {1, -1, 0, 0, 1, -1, 1, -1, 0};
template <class T> inline bool chmin(T &a, T b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}
template <class T> inline bool chmax(T &a, T b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}

template <typename X, typename M>
struct
    SegTreeLazy { // 遅延セグ木　単位元に注意(updateなら選ばれない数、affineなら(1,0))
  using FX = function<X(X, X)>;
  using FA = function<X(X, M)>;
  using FM = function<M(M, M)>;
  int n;
  FX fx;
  FA fa;
  FM fm;
  const X ex;
  const M em;
  vector<X> dat;
  vector<M> lazy;
  SegTreeLazy(int n_, FX fx_, FA fa_, FM fm_, X ex_, M em_)
      : n(), fx(fx_), fa(fa_), fm(fm_), ex(ex_), em(em_), dat(n_ * 4, ex),
        lazy(n_ * 4, em) {
    int x = 1;
    while (n_ > x)
      x *= 2;
    n = x;
  }
  void set(int i, X x) { dat[i + n - 1] = x; }
  void build() {
    for (int k = n - 2; k >= 0; k--)
      dat[k] = fx(dat[2 * k + 1], dat[2 * k + 2]);
  }
  /* lazy eval */
  void eval(int k, int len) {
    if (lazy[k] == em)
      return;        // 更新するものが無ければ終了
    if (k < n - 1) { // 葉でなければ子に伝搬
      lazy[k * 2 + 1] = fm(lazy[k * 2 + 1], lazy[k]);
      lazy[k * 2 + 2] = fm(lazy[k * 2 + 2], lazy[k]);
    }
    // 自身を更新
    dat[k] = fa(dat[k], lazy[k]); // fa(dat[k], fp(lazy[k], len));
    lazy[k] = em;
  }
  void update(int a, int b, M x, int k, int l, int r) {
    eval(k, r - l);
    if (a <= l && r <= b) { // 完全に内側の時
      lazy[k] = fm(lazy[k], x);
      eval(k, r - l);
    } else if (a < r && l < b) {                  // 一部区間が被る時
      update(a, b, x, k * 2 + 1, l, (l + r) / 2); // 左の子
      update(a, b, x, k * 2 + 2, (l + r) / 2, r); // 右の子
      dat[k] = fx(dat[k * 2 + 1], dat[k * 2 + 2]);
    }
  }
  void update(int a, int b, M x) { update(a, b, x, 0, 0, n); }
  X query_sub(int a, int b, int k, int l, int r) {
    eval(k, r - l);
    if (r <= a || b <= l) { // 完全に外側の時
      return ex;
    } else if (a <= l && r <= b) { // 完全に内側の時
      return dat[k];
    } else { // 一部区間が被る時
      X vl = query_sub(a, b, k * 2 + 1, l, (l + r) / 2);
      X vr = query_sub(a, b, k * 2 + 2, (l + r) / 2, r);
      return fx(vl, vr);
    }
  }
  X query(int a, int b) { return query_sub(a, b, 0, 0, n); }
  X operator[](int i) { return query(i, i + 1); }
};

const int mod = MOD9;
struct mint {
  ll x; // typedef long long ll;
  mint(ll x = 0) : x((x % mod + mod) % mod) {}
  mint operator-() const { return mint(-x); }
  mint &operator+=(const mint a) {
    if ((x += a.x) >= mod)
      x -= mod;
    return *this;
  }
  mint &operator-=(const mint a) {
    if ((x += mod - a.x) >= mod)
      x -= mod;
    return *this;
  }
  mint &operator*=(const mint a) {
    (x *= a.x) %= mod;
    return *this;
  }
  mint operator+(const mint a) const { return mint(*this) += a; }
  mint operator-(const mint a) const { return mint(*this) -= a; }
  mint operator*(const mint a) const { return mint(*this) *= a; }
  mint pow(ll t) const {
    if (!t)
      return 1;
    mint a = pow(t >> 1);
    a *= a;
    if (t & 1)
      a *= *this;
    return a;
  }
  bool operator==(const mint &p) const { return x == p.x; }
  bool operator!=(const mint &p) const { return x != p.x; }
  // for prime mod
  mint inv() const { return pow(mod - 2); }
  mint &operator/=(const mint a) { return *this *= a.inv(); }
  mint operator/(const mint a) const { return mint(*this) /= a; }
};
istream &operator>>(istream &is, mint &a) { return is >> a.x; }
ostream &operator<<(ostream &os, const mint &a) { return os << a.x; }

using pm = pair<mint, int>;
vector<mint> tenpow(200010);
int main() {
  ll n, q;
  cin >> n >> q;
  tenpow[0] = 1;
  rep(i, 200009) tenpow[i + 1] = tenpow[i] * 10;
  auto fx = [](pm a, pm b) {
    a.fi *= tenpow[b.se];
    a.fi += b.fi;
    a.se += b.se;
    return a;
  };
  auto fa = [](pm a, int d) {
    a.fi = tenpow[a.se] - 1;
    a.fi /= 9;
    a.fi *= d;
    return a;
  };
  auto fm = [](int a, int b) { return b; };
  SegTreeLazy<pm, int> st(n, fx, fa, fm, {0, 0}, 0);
  rep(i, n) st.set(i, {1, 1});
  st.build();
  while (q--) {
    int l, r, d;
    scanf("%d", &l);
    scanf("%d", &r);
    scanf("%d", &d);
    l--;
    st.update(l, r, d);
    // cout << st.dat[0].fi <<endl;
    printf("%lld\n", st.dat[0].fi.x);
  }
}

Fixed submission:
#include <bits/stdc++.h>
using namespace std;
#define rep(i, n) for (ll i = 0; i < n; i++)
#define repl(i, l, r) for (ll i = (l); i < (r); i++)
#define per(i, n) for (ll i = n - 1; i >= 0; i--)
#define perl(i, r, l) for (ll i = r - 1; i >= l; i--)
#define fi first
#define se second
#define pb push_back
#define ins insert
#define pqueue(x) priority_queue<x, vector<x>, greater<x>>
#define all(x) (x).begin(), (x).end()
#define CST(x) cout << fixed << setprecision(x)
#define vtpl(x, y, z) vector<tuple<x, y, z>>
#define rev(x) reverse(x);
using ll = long long;
using vl = vector<ll>;
using vvl = vector<vector<ll>>;
using pl = pair<ll, ll>;
using vpl = vector<pl>;
using vvpl = vector<vpl>;
const ll MOD = 1000000007;
const ll MOD9 = 998244353;
const int inf = 1e9 + 10;
const ll INF = 4e18;
const ll dy[9] = {0, 0, 1, -1, 1, 1, -1, -1, 0};
const ll dx[9] = {1, -1, 0, 0, 1, -1, 1, -1, 0};
template <class T> inline bool chmin(T &a, T b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}
template <class T> inline bool chmax(T &a, T b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}

template <typename X, typename M>
struct
    SegTreeLazy { // 遅延セグ木　単位元に注意(updateなら選ばれない数、affineなら(1,0))
  using FX = function<X(X, X)>;
  using FA = function<X(X, M)>;
  using FM = function<M(M, M)>;
  int n;
  FX fx;
  FA fa;
  FM fm;
  const X ex;
  const M em;
  vector<X> dat;
  vector<M> lazy;
  SegTreeLazy(int n_, FX fx_, FA fa_, FM fm_, X ex_, M em_)
      : n(), fx(fx_), fa(fa_), fm(fm_), ex(ex_), em(em_), dat(n_ * 4, ex),
        lazy(n_ * 4, em) {
    int x = 1;
    while (n_ > x)
      x *= 2;
    n = x;
  }
  void set(int i, X x) { dat[i + n - 1] = x; }
  void build() {
    for (int k = n - 2; k >= 0; k--)
      dat[k] = fx(dat[2 * k + 1], dat[2 * k + 2]);
  }
  /* lazy eval */
  void eval(int k, int len) {
    if (lazy[k] == em)
      return;        // 更新するものが無ければ終了
    if (k < n - 1) { // 葉でなければ子に伝搬
      lazy[k * 2 + 1] = fm(lazy[k * 2 + 1], lazy[k]);
      lazy[k * 2 + 2] = fm(lazy[k * 2 + 2], lazy[k]);
    }
    // 自身を更新
    dat[k] = fa(dat[k], lazy[k]); // fa(dat[k], fp(lazy[k], len));
    lazy[k] = em;
  }
  void update(int a, int b, M x, int k, int l, int r) {
    eval(k, r - l);
    if (a <= l && r <= b) { // 完全に内側の時
      lazy[k] = fm(lazy[k], x);
      eval(k, r - l);
    } else if (a < r && l < b) {                  // 一部区間が被る時
      update(a, b, x, k * 2 + 1, l, (l + r) / 2); // 左の子
      update(a, b, x, k * 2 + 2, (l + r) / 2, r); // 右の子
      dat[k] = fx(dat[k * 2 + 1], dat[k * 2 + 2]);
    }
  }
  void update(int a, int b, M x) { update(a, b, x, 0, 0, n); }
  X query_sub(int a, int b, int k, int l, int r) {
    eval(k, r - l);
    if (r <= a || b <= l) { // 完全に外側の時
      return ex;
    } else if (a <= l && r <= b) { // 完全に内側の時
      return dat[k];
    } else { // 一部区間が被る時
      X vl = query_sub(a, b, k * 2 + 1, l, (l + r) / 2);
      X vr = query_sub(a, b, k * 2 + 2, (l + r) / 2, r);
      return fx(vl, vr);
    }
  }
  X query(int a, int b) { return query_sub(a, b, 0, 0, n); }
  X operator[](int i) { return query(i, i + 1); }
};

const int mod = MOD9;
struct mint {
  ll x; // typedef long long ll;
  mint(ll x = 0) : x((x % mod + mod) % mod) {}
  mint operator-() const { return mint(-x); }
  mint &operator+=(const mint a) {
    if ((x += a.x) >= mod)
      x -= mod;
    return *this;
  }
  mint &operator-=(const mint a) {
    if ((x += mod - a.x) >= mod)
      x -= mod;
    return *this;
  }
  mint &operator*=(const mint a) {
    (x *= a.x) %= mod;
    return *this;
  }
  mint operator+(const mint a) const { return mint(*this) += a; }
  mint operator-(const mint a) const { return mint(*this) -= a; }
  mint operator*(const mint a) const { return mint(*this) *= a; }
  mint pow(ll t) const {
    if (!t)
      return 1;
    mint a = pow(t >> 1);
    a *= a;
    if (t & 1)
      a *= *this;
    return a;
  }
  bool operator==(const mint &p) const { return x == p.x; }
  bool operator!=(const mint &p) const { return x != p.x; }
  // for prime mod
  mint inv() const { return pow(mod - 2); }
  mint &operator/=(const mint a) { return *this *= a.inv(); }
  mint operator/(const mint a) const { return mint(*this) /= a; }
};
istream &operator>>(istream &is, mint &a) { return is >> a.x; }
ostream &operator<<(ostream &os, const mint &a) { return os << a.x; }

using pm = pair<mint, int>;
vector<mint> tenpow(200010);
int main() {
  ll n, q;
  cin >> n >> q;
  tenpow[0] = 1;
  rep(i, 200009) tenpow[i + 1] = tenpow[i] * 10;
  auto fx = [](pm a, pm b) {
    a.fi *= tenpow[b.se];
    a.fi += b.fi;
    a.se += b.se;
    return a;
  };
  auto fa = [](pm a, int d) {
    a.fi = tenpow[a.se] - 1;
    a.fi *= 443664157;
    a.fi *= d;
    return a;
  };
  auto fm = [](int a, int b) { return b; };
  SegTreeLazy<pm, int> st(n, fx, fa, fm, {0, 0}, 0);
  rep(i, n) st.set(i, {1, 1});
  st.build();
  while (q--) {
    int l, r, d;
    scanf("%d", &l);
    scanf("%d", &r);
    scanf("%d", &d);
    l--;
    st.update(l, r, d);
    // cout << st.dat[0].fi <<endl;
    printf("%lld\n", st.dat[0].fi.x);
  }
}