Problem p02538 (C++)

Buggy submission (status: Time Limit Exceeded):
#pragma GCC optimize("Ofast")
#pragma GCC target("avx,avx2,fma")
#include <bits/stdc++.h>
using namespace std;
#define mp make_pair
#define INF 10000000
#define MOD 998244353
#define MID (l + r) / 2
#define HASHMOD 2305843009213693951
#define ll long long
#define ull unsigned long long
#define F first
#define S second
typedef pair<ll, ll> ii;
typedef pair<ii, int> iii;
typedef vector<int> vi;
typedef vector<ii> vii;
typedef map<int, int> mii;

#define EPS 1e-6
#define FOR(i, n) for (int i = 0; i < ((int)(n)); i++)
#define FORi(i, a, b) for (int i = ((int)(a)); i < ((int)(b)); i++)
#define FOA(v, a) for (auto v : a)

int t, n;
vi a, b;

ll mpow(ll a, ll b) {
  if (b == 0)
    return 1;
  if (b == 1)
    return a;
  ll z = mpow(a, b / 2);
  z *= z;
  z %= MOD;
  if (b % 2)
    z *= a;
  return z % MOD;
}

long long inv(int s) { return mpow(s, MOD - 2); }

template <typename T> struct seg_tree {
  struct node {
    T val;
    T laz;
    int left = -1;
    int right = -1;
    node() { val = 0, laz = 0, left = -1, right = -1; }
    node(T v) { val = v, laz = 0, right = -1, left = -1; }
  };
  vector<node> seg;
  static inline int N;
  const int RAND_VALUE = 0;
  seg_tree(int n) { N = n, seg.assign(1, node()); }

  inline node merge(node par, node a, node b, int lw) {
    // cout<<a.val<<" "<<b.val<<endl;
    node ret;
    ret.left = par.left, ret.right = par.right;
    ret.val = ((a.val * mpow(10, lw)) % MOD + b.val) % MOD;
    assert(!par.laz);
    return ret;
  }

  inline void update_node(int ind, int val, int l, int r) {
    // cout<<"U"<<val<<" "<<l<<" "<<r<<" "<<ind<<" "<<endl;
    seg[ind].val = ((val * (mpow(10, r - l + 1) - 1)) % MOD * inv(9)) % MOD;
    seg[ind].laz = val;
    assert(seg[ind].laz);
    // cout<<seg[ind].laz<<endl;
  }

  inline void down(int ind, int l, int r) {
    node par = seg[ind];
    // cout<<l<<" "<<r<<" "<<ind<<" "<<par.laz<<endl;
    if (par.laz) {
      // cout<<"bla\n";
      seg[par.left].val =
          ((par.laz * (mpow(10, MID - l + 1) - 1)) % MOD * inv(9)) % MOD;
      seg[par.right].val =
          ((par.laz * (mpow(10, r - MID) - 1)) % MOD * inv(9)) % MOD;
      seg[par.left].laz = par.laz;
      seg[par.right].laz = par.laz;
    }

    seg[ind].laz = 0;
  }

  inline void create_children(int ind) {
    node par = seg[ind];
    if (par.left == -1) {
      // cout<<"left\n";
      par.left = seg.size(), seg.push_back(node());
    }
    if (par.right == -1)
      par.right = seg.size(), seg.push_back(node());
    seg[ind] = par;
  }

  void build(int l = 0, int r = N - 1, int ind = 0) {
    if (l == r)
      seg[ind] = node(1);
    else {
      create_children(ind);
      build(l, MID, seg[ind].left);
      build(MID + 1, r, seg[ind].right);

      seg[ind] =
          merge(seg[ind], seg[seg[ind].left], seg[seg[ind].right], (r - MID));
    }
  }

  void update(int rl, int rr, int val, int l = 0, int r = N - 1, int ind = 0) {
    if (rl <= l && r <= rr)
      update_node(ind, val, l, r);
    else if (rr < l || r < rl)
      return;
    else {
      create_children(ind);
      down(ind, l, r);
      assert(seg[ind].laz == 0);
      update(rl, rr, val, l, MID, seg[ind].left);
      update(rl, rr, val, MID + 1, r, seg[ind].right);
      seg[ind] =
          merge(seg[ind], seg[seg[ind].left], seg[seg[ind].right], (r - MID));
    }
  }

  node _query(int rl, int rr, int l = 0, int r = N - 1, int ind = 0) {
    if (rl <= l && r <= rr)
      return seg[ind];
    else if (rl > r || l > rr)
      return RAND_VALUE;
    else {
      create_children(ind);
      down(ind, l, r);
      return merge(seg[ind], _query(rl, rr, l, MID, seg[ind].left),
                   _query(rl, rr, MID + 1, r, seg[ind].right), (r - MID));
    }
  }

  T query(int l, int r) { return _query(l, r).val % MOD; }
};

int main() {
  int q;
  cin >> n >> q;
  seg_tree<long long> seg(n);
  seg.build();
  while (q--) {
    int l, r, d;
    cin >> l >> r >> d;
    l--, r--;
    seg.update(l, r, d);
    cout << seg.query(0, n - 1) << endl;
  }
}


Fixed submission:
#pragma GCC optimize("Ofast")
#pragma GCC target("avx,avx2,fma")
#include <bits/stdc++.h>
using namespace std;
#define mp make_pair
#define INF 10000000
#define MOD 998244353
#define MID (l + r) / 2
#define HASHMOD 2305843009213693951
#define ll long long
#define ull unsigned long long
#define F first
#define S second
typedef pair<ll, ll> ii;
typedef pair<ii, int> iii;
typedef vector<int> vi;
typedef vector<ii> vii;
typedef map<int, int> mii;

#define EPS 1e-6
#define FOR(i, n) for (int i = 0; i < ((int)(n)); i++)
#define FORi(i, a, b) for (int i = ((int)(a)); i < ((int)(b)); i++)
#define FOA(v, a) for (auto v : a)

int t, n;
vi a, b;

ll mpow(ll a, ll b) {
  if (b == 0)
    return 1;
  if (b == 1)
    return a;
  ll z = mpow(a, b / 2);
  z *= z;
  z %= MOD;
  if (b % 2)
    z *= a;
  return z % MOD;
}

#define inv(v) (443664157ll)
template <typename T> struct seg_tree {
  struct node {
    T val;
    T laz;
    int left = -1;
    int right = -1;
    node() { val = 0, laz = 0, left = -1, right = -1; }
    node(T v) { val = v, laz = 0, right = -1, left = -1; }
  };
  vector<node> seg;
  static inline int N;
  const int RAND_VALUE = 0;
  seg_tree(int n) { N = n, seg.assign(1, node()); }

  inline node merge(node par, node a, node b, int lw) {
    // cout<<a.val<<" "<<b.val<<endl;
    node ret;
    ret.left = par.left, ret.right = par.right;
    ret.val = ((a.val * mpow(10, lw)) % MOD + b.val) % MOD;
    assert(!par.laz);
    return ret;
  }

  inline void update_node(int ind, int val, int l, int r) {
    // cout<<"U"<<val<<" "<<l<<" "<<r<<" "<<ind<<" "<<endl;
    seg[ind].val = ((val * (mpow(10, r - l + 1) - 1)) % MOD * inv(9)) % MOD;
    seg[ind].laz = val;
    assert(seg[ind].laz);
    // cout<<seg[ind].laz<<endl;
  }

  inline void down(int ind, int l, int r) {
    node par = seg[ind];
    // cout<<l<<" "<<r<<" "<<ind<<" "<<par.laz<<endl;
    if (par.laz) {
      // cout<<"bla\n";
      seg[par.left].val =
          ((par.laz * (mpow(10, MID - l + 1) - 1)) % MOD * inv(9)) % MOD;
      seg[par.right].val =
          ((par.laz * (mpow(10, r - MID) - 1)) % MOD * inv(9)) % MOD;
      seg[par.left].laz = par.laz;
      seg[par.right].laz = par.laz;
    }

    seg[ind].laz = 0;
  }

  inline void create_children(int ind) {
    node par = seg[ind];
    if (par.left == -1) {
      // cout<<"left\n";
      par.left = seg.size(), seg.push_back(node());
    }
    if (par.right == -1)
      par.right = seg.size(), seg.push_back(node());
    seg[ind] = par;
  }

  void build(int l = 0, int r = N - 1, int ind = 0) {
    if (l == r)
      seg[ind] = node(1);
    else {
      create_children(ind);
      build(l, MID, seg[ind].left);
      build(MID + 1, r, seg[ind].right);

      seg[ind] =
          merge(seg[ind], seg[seg[ind].left], seg[seg[ind].right], (r - MID));
    }
  }

  void update(int rl, int rr, int val, int l = 0, int r = N - 1, int ind = 0) {
    if (rl <= l && r <= rr)
      update_node(ind, val, l, r);
    else if (rr < l || r < rl)
      return;
    else {
      create_children(ind);
      down(ind, l, r);
      assert(seg[ind].laz == 0);
      update(rl, rr, val, l, MID, seg[ind].left);
      update(rl, rr, val, MID + 1, r, seg[ind].right);
      seg[ind] =
          merge(seg[ind], seg[seg[ind].left], seg[seg[ind].right], (r - MID));
    }
  }

  node _query(int rl, int rr, int l = 0, int r = N - 1, int ind = 0) {
    if (rl <= l && r <= rr)
      return seg[ind];
    else if (rl > r || l > rr)
      return RAND_VALUE;
    else {
      create_children(ind);
      down(ind, l, r);
      return merge(seg[ind], _query(rl, rr, l, MID, seg[ind].left),
                   _query(rl, rr, MID + 1, r, seg[ind].right), (r - MID));
    }
  }

  T query(int l, int r) { return _query(l, r).val % MOD; }
};

int main() {
  int q;
  cin >> n >> q;
  seg_tree<long long> seg(n);
  seg.build();
  while (q--) {
    int l, r, d;
    cin >> l >> r >> d;
    l--, r--;
    seg.update(l, r, d);
    cout << seg.query(0, n - 1) << endl;
  }
}