Problem p02538 (C++) — buggy submission, verdict: Time Limit Exceeded

#pragma GCC optimize("Ofast")
#pragma region head
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using vi = vector<int>;
using vll = vector<ll>;
using pi = pair<int, int>;
using pll = pair<ll, ll>;
template <class T> using vv = vector<vector<T>>;
#define rep(i, n) for (int i = 0; i < (int)(n); i++)
#define repi(i, a, b) for (int i = (int)(a); i < (int)(b); i++)
#define rrep(i, n) for (int i = (int)(n)-1; i >= 0; i--)
#define rrepi(i, a, b) for (int i = (int)(b)-1; i >= (int)(a); i--)
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define bit(n) (1LL << (n))
template <class T> inline bool chmax(T &a, const T &b) {
  if (a < b) {
    a = b;
    return 1;
  }
  return 0;
}
template <class T> inline bool chmin(T &a, const T &b) {
  if (a > b) {
    a = b;
    return 1;
  }
  return 0;
}
const int INF = 1002003004;
const ll LINF = 1002003004005006007ll;
struct preprocess {
  preprocess() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(20);
  }
} ____;
#pragma endregion head

#pragma region library
const int MOD = 998244353;
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 {
    mint res(*this);
    return res += a;
  }
  mint operator-(const mint a) const {
    mint res(*this);
    return res -= a;
  }
  mint operator*(const mint a) const {
    mint res(*this);
    return res *= a;
  }
  mint pow(ll t) const {
    if (!t)
      return 1;
    mint a = pow(t >> 1);
    a *= a;
    if (t & 1)
      a *= *this;
    return a;
  }
  // 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 {
    mint res(*this);
    return res /= a;
  }
  bool operator==(const mint a) const { return x == a.x; }
  bool operator!=(const mint a) const { return x != a.x; }
  friend ostream &operator<<(ostream &os, const mint &value) {
    os << value.x;
    return os;
  }
  friend istream &operator>>(istream &is, mint &value) {
    ll t;
    is >> t;
    value = mint(t);
    return is;
  }
};

// Time Complexity: build O(N), query O(logN)
template <typename T, typename U = T> struct LazySegmentTree {
  // T should be Monoid (Associativity, Identity element)
  using FuncTT = function<T(T, T)>;
  using FuncTU = function<T(T, U)>;
  using FuncUU = function<U(U, U)>;
  int sz;         // size of array
  vector<T> data; // 1-indexed(size: sz*2)
  vector<U> lazy;
  T identity; // identity element
  U identityLz;
  FuncTT f;
  FuncTU g;
  FuncUU h;

  // node k: parent k/2, children (2*k, 2*k+1)
  LazySegmentTree(int n, const T &identity, const U &identityLz, FuncTT f,
                  FuncTU g, FuncUU h)
      : identity(identity), identityLz(identityLz), f(f), g(g), h(h) {
    sz = 1;
    while (sz < n)
      sz <<= 1;
    data.assign(2 * sz, identity);
    lazy.assign(2 * sz, identityLz);
  }
  void set(int idx, const T &val) { data[idx + sz] = val; }
  void build() {
    for (int idx = sz - 1; idx > 0; idx--) {
      data[idx] = f(data[2 * idx], data[2 * idx + 1]);
    }
  }
  inline void evaluate(int idx) {
    if (lazy[idx] != identityLz) {
      if (idx < sz) {
        lazy[2 * idx] = h(lazy[2 * idx], lazy[idx]);
        lazy[2 * idx + 1] = h(lazy[2 * idx + 1], lazy[idx]);
      }
      data[idx] = reflect(idx);
      lazy[idx] = identityLz;
    }
  }
  inline T reflect(int idx) {
    if (lazy[idx] != identityLz)
      return g(data[idx], lazy[idx]);
    else
      return data[idx];
  }
  void update(int a, int b, const U &x) { update(a, b, x, 1, 0, sz); }
  void update(int a, int b, const U &x, int idx, int l, int r) {
    evaluate(idx);
    if (b <= l || r <= a)
      return;
    if (a <= l && r <= b) {
      lazy[idx] = h(lazy[idx], x);
      evaluate(idx);
    } else {
      update(a, b, x, 2 * idx, l, (l + r) / 2);
      update(a, b, x, 2 * idx + 1, (l + r) / 2, r);
      data[idx] = f(data[2 * idx], data[2 * idx + 1]);
    }
  }
  // [a, b)
  // recursive implementation
  T query(int a, int b) { return query(a, b, 1, 0, sz); }
  T query(int a, int b, int idx, int l, int r) {
    if (r <= a || b <= l)
      return identity;
    evaluate(idx);
    if (a <= l && r <= b)
      return data[idx];
    else {
      T vl = query(a, b, idx * 2, l, (l + r) / 2);
      T vr = query(a, b, idx * 2 + 1, (l + r) / 2, r);
      return f(vl, vr);
    }
  }
  // ToDo: for-loop implementation
  // T query(int l, int r)
  T operator[](const int &idx) { return query(idx, idx + 1); }
};
// Time Complexity: build O(N), query O(logN)
template <typename T> struct SegmentTree {
  // T should be Monoid (Associativity, Identity element)
  using Func = function<T(T, T)>;
  int sz;         // size of array
  vector<T> data; // 1-indexed(size: sz*2)
  T identity;     // identity element
  Func f;         // binary operation
  // node k: parent k/2, children (2*k, 2*k+1)
  SegmentTree() = default;
  SegmentTree(int n, const T &identity, Func f) : identity(identity), f(f) {
    sz = 1;
    while (sz < n)
      sz <<= 1;
    data.assign(2 * sz, identity);
  }
  void set(int idx, const T &val) { data[idx + sz] = val; }
  void build() {
    for (int idx = sz - 1; idx > 0; idx--) {
      data[idx] = f(data[2 * idx], data[2 * idx + 1]);
    }
  }
  void update(int idx, const T &x) {
    idx += sz;
    data[idx] = x;
    while (idx >>= 1) {
      data[idx] = f(data[2 * idx], data[2 * idx + 1]);
    }
  }
  // [a, b)
  // recursive implementation
  T query(int a, int b) { return query(a, b, 1, 0, sz); }
  T query(int a, int b, int idx, int l, int r) {
    if (r <= a || b <= l)
      return identity;
    if (a <= l && r <= b)
      return data[idx];
    else {
      T vl = query(a, b, idx * 2, l, (l + r) / 2);
      T vr = query(a, b, idx * 2 + 1, (l + r) / 2, r);
      return f(vl, vr);
    }
  }
  // ToDo: for-loop implementation
  // T query(int l, int r)
  T operator[](const int &idx) const { return data[idx + sz]; }
};
// Complexity: O(log n)
ll modpow(ll x, ll n, const ll mod) {
  if (!n)
    return 1;
  ll res = modpow(x * x % mod, n / 2, mod);
  if (n & 1)
    res = res * x % mod;
  return res;
}
#pragma endregion library
SegmentTree<mint> sg1;
using ti = tuple<mint, int, int>;
ti id = ti{0, -1, -1};
ti f(ti a, ti b) {
  if (a == id)
    return b;
  if (b == id)
    return a;
  mint a1, b1;
  int a2, a3, b2, b3;
  tie(a1, a2, a3) = a;
  tie(b1, b2, b3) = b;
  return ti{a1 + b1, min(a2, b2), max(a3, b3)};
}
ti g(ti a, int x) {
  if (a == id)
    return a;
  mint a1;
  int a2, a3;
  tie(a1, a2, a3) = a;
  mint val = 0;
  if (a2 != -1)
    val = sg1.query(a2, a3);
  return ti{val * x, a2, a3};
}
int h(int a, int b) { return b; }
mint f2(mint a, mint b) { return a + b; }

int main() {
  int n, q;
  cin >> n >> q;
  sg1 = SegmentTree<mint>(n, 0, f2);
  rep(i, n) { sg1.set(i, modpow(10, n - i - 1, MOD)); }
  sg1.build();
  LazySegmentTree<ti, int> sg2(n, ti{0, -1, -1}, 0, f, g, h);
  rep(i, n) {
    mint val = sg1[i];
    sg2.set(i, ti{val, i, i + 1});
  }
  sg2.build();
  while (q--) {
    int l, r, d;
    cin >> l >> r >> d;
    l--;
    sg2.update(l, r, d);
    mint ans;
    tie(ans, ignore, ignore) = sg2.query(0, n);
    cout << ans << '\\n';
  }
}


Error: TLE

Fixed submission:

#pragma region head
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using vi = vector<int>;
using vll = vector<ll>;
using pi = pair<int, int>;
using pll = pair<ll, ll>;
template <class T> using vv = vector<vector<T>>;
#define rep(i, n) for (int i = 0; i < (int)(n); i++)
#define repi(i, a, b) for (int i = (int)(a); i < (int)(b); i++)
#define rrep(i, n) for (int i = (int)(n)-1; i >= 0; i--)
#define rrepi(i, a, b) for (int i = (int)(b)-1; i >= (int)(a); i--)
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define bit(n) (1LL << (n))
template <class T> inline bool chmax(T &a, const T &b) {
  if (a < b) {
    a = b;
    return 1;
  }
  return 0;
}
template <class T> inline bool chmin(T &a, const T &b) {
  if (a > b) {
    a = b;
    return 1;
  }
  return 0;
}
const int INF = 1002003004;
const ll LINF = 1002003004005006007ll;
struct preprocess {
  preprocess() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(20);
  }
} ____;
#pragma endregion head

#pragma region library
const int MOD = 998244353;
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 {
    mint res(*this);
    return res += a;
  }
  mint operator-(const mint a) const {
    mint res(*this);
    return res -= a;
  }
  mint operator*(const mint a) const {
    mint res(*this);
    return res *= a;
  }
  mint pow(ll t) const {
    if (!t)
      return 1;
    mint a = pow(t >> 1);
    a *= a;
    if (t & 1)
      a *= *this;
    return a;
  }
  // 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 {
    mint res(*this);
    return res /= a;
  }
  bool operator==(const mint a) const { return x == a.x; }
  bool operator!=(const mint a) const { return x != a.x; }
  friend ostream &operator<<(ostream &os, const mint &value) {
    os << value.x;
    return os;
  }
  friend istream &operator>>(istream &is, mint &value) {
    ll t;
    is >> t;
    value = mint(t);
    return is;
  }
};

// Time Complexity: build O(N), query O(logN)
template <typename T, typename U = T> struct LazySegmentTree {
  // T should be Monoid (Associativity, Identity element)
  using FuncTT = function<T(T, T)>;
  using FuncTU = function<T(T, U)>;
  using FuncUU = function<U(U, U)>;
  int sz;         // size of array
  vector<T> data; // 1-indexed(size: sz*2)
  vector<U> lazy;
  T identity; // identity element
  U identityLz;
  FuncTT f;
  FuncTU g;
  FuncUU h;

  // node k: parent k/2, children (2*k, 2*k+1)
  LazySegmentTree(int n, const T &identity, const U &identityLz, FuncTT f,
                  FuncTU g, FuncUU h)
      : identity(identity), identityLz(identityLz), f(f), g(g), h(h) {
    sz = 1;
    while (sz < n)
      sz <<= 1;
    data.assign(2 * sz, identity);
    lazy.assign(2 * sz, identityLz);
  }
  void set(int idx, const T &val) { data[idx + sz] = val; }
  void build() {
    for (int idx = sz - 1; idx > 0; idx--) {
      data[idx] = f(data[2 * idx], data[2 * idx + 1]);
    }
  }
  inline void evaluate(int idx) {
    if (lazy[idx] != identityLz) {
      if (idx < sz) {
        lazy[2 * idx] = h(lazy[2 * idx], lazy[idx]);
        lazy[2 * idx + 1] = h(lazy[2 * idx + 1], lazy[idx]);
      }
      data[idx] = reflect(idx);
      lazy[idx] = identityLz;
    }
  }
  inline T reflect(int idx) {
    if (lazy[idx] != identityLz)
      return g(data[idx], lazy[idx]);
    else
      return data[idx];
  }
  void update(int a, int b, const U &x) { update(a, b, x, 1, 0, sz); }
  void update(int a, int b, const U &x, int idx, int l, int r) {
    evaluate(idx);
    if (b <= l || r <= a)
      return;
    if (a <= l && r <= b) {
      lazy[idx] = h(lazy[idx], x);
      evaluate(idx);
    } else {
      update(a, b, x, 2 * idx, l, (l + r) / 2);
      update(a, b, x, 2 * idx + 1, (l + r) / 2, r);
      data[idx] = f(data[2 * idx], data[2 * idx + 1]);
    }
  }
  // [a, b)
  // recursive implementation
  T query(int a, int b) { return query(a, b, 1, 0, sz); }
  T query(int a, int b, int idx, int l, int r) {
    if (r <= a || b <= l)
      return identity;
    evaluate(idx);
    if (a <= l && r <= b)
      return data[idx];
    else {
      T vl = query(a, b, idx * 2, l, (l + r) / 2);
      T vr = query(a, b, idx * 2 + 1, (l + r) / 2, r);
      return f(vl, vr);
    }
  }
  // ToDo: for-loop implementation
  // T query(int l, int r)
  T operator[](const int &idx) { return query(idx, idx + 1); }
};
// Time Complexity: build O(N), query O(logN)
template <typename T> struct SegmentTree {
  // T should be Monoid (Associativity, Identity element)
  using Func = function<T(T, T)>;
  int sz;         // size of array
  vector<T> data; // 1-indexed(size: sz*2)
  T identity;     // identity element
  Func f;         // binary operation
  // node k: parent k/2, children (2*k, 2*k+1)
  SegmentTree() = default;
  SegmentTree(int n, const T &identity, Func f) : identity(identity), f(f) {
    sz = 1;
    while (sz < n)
      sz <<= 1;
    data.assign(2 * sz, identity);
  }
  void set(int idx, const T &val) { data[idx + sz] = val; }
  void build() {
    for (int idx = sz - 1; idx > 0; idx--) {
      data[idx] = f(data[2 * idx], data[2 * idx + 1]);
    }
  }
  void update(int idx, const T &x) {
    idx += sz;
    data[idx] = x;
    while (idx >>= 1) {
      data[idx] = f(data[2 * idx], data[2 * idx + 1]);
    }
  }
  // [a, b)
  // recursive implementation
  T query(int a, int b) { return query(a, b, 1, 0, sz); }
  T query(int a, int b, int idx, int l, int r) {
    if (r <= a || b <= l)
      return identity;
    if (a <= l && r <= b)
      return data[idx];
    else {
      T vl = query(a, b, idx * 2, l, (l + r) / 2);
      T vr = query(a, b, idx * 2 + 1, (l + r) / 2, r);
      return f(vl, vr);
    }
  }
  // ToDo: for-loop implementation
  // T query(int l, int r)
  T operator[](const int &idx) const { return data[idx + sz]; }
};
// Complexity: O(log n)
ll modpow(ll x, ll n, const ll mod) {
  if (!n)
    return 1;
  ll res = modpow(x * x % mod, n / 2, mod);
  if (n & 1)
    res = res * x % mod;
  return res;
}
#pragma endregion library
SegmentTree<mint> sg1;
using ti = tuple<mint, int, int>;
ti f(ti a, ti b) {
  mint a1, b1;
  int a2, a3, b2, b3;
  tie(a1, a2, a3) = a;
  tie(b1, b2, b3) = b;
  if (a2 == -1)
    return b;
  if (b3 == -1)
    return a;
  return ti{a1 + b1, min(a2, b2), max(a3, b3)};
}
ti g(ti a, int x) {
  mint a1;
  int a2, a3;
  tie(a1, a2, a3) = a;
  mint val = 0;
  if (a2 != -1)
    val = sg1.query(a2, a3);
  return ti{val * x, a2, a3};
}
int h(int a, int b) { return b; }
mint f2(mint a, mint b) { return a + b; }

int main() {
  int n, q;
  cin >> n >> q;
  sg1 = SegmentTree<mint>(n, 0, f2);
  rep(i, n) { sg1.set(i, modpow(10, n - i - 1, MOD)); }
  sg1.build();
  LazySegmentTree<ti, int> sg2(n, ti{0, -1, -1}, 0, f, g, h);
  rep(i, n) {
    mint val = modpow(10, n - i - 1, MOD);
    sg2.set(i, ti{val, i, i + 1});
  }
  sg2.build();
  while (q--) {
    int l, r, d;
    cin >> l >> r >> d;
    l--;
    sg2.update(l, r, d);
    mint ans;
    tie(ans, ignore, ignore) = sg2.query(0, n);
    cout << ans << '\\n';
  }
}