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

#include <bits/stdc++.h>
using namespace std;
#define MAXN 1000010
#define optimizar_io                                                           \\
  ios_base::sync_with_stdio(false);                                            \\
  cin.tie(0);
typedef long long int ll;

ll arr[MAXN], acum[MAXN];

ll mod(ll a, ll b = 998244353) { return ((a % b) + b) % b; }

ll powMod(ll a, ll n, ll m = 998244353) {
  ll result = 1;
  while (n) {
    if (n & 1)
      result = mod(result * a, m);
    a = mod(a * a, m);
    n >>= 1;
  }
  return result;
}

ll modInv(ll a, ll n = 998244353) { return powMod(a, n - 2); }

ll geometrica(ll x, ll n) {
  ll ans = powMod(x, n + 1);
  ans--;
  ll inv = modInv(x - 1);
  ll power_sum = mod(ans * inv);
  return power_sum;
}

ll range(int l, int r) {
  if (l == 0)
    return acum[r];
  else
    return mod(acum[r] - acum[l - 1]);
}

struct Node {
  ll sum;

  void make_Node(ll v, int idx) { sum = mod(v * powMod(10, idx)); }

  void merge(Node left, Node right) { sum = mod(left.sum + right.sum); }

  ll getValue() { return sum; }
};

struct SegmentTree {

  Node *stree;
  vector<ll> lazy;

  SegmentTree(int N) {
    stree = new Node[getSegmentTreeSize(N)];
    lazy.assign(getSegmentTreeSize(N), 0);
    buildTree(1, 0, N - 1);
  }

  void buildTree(int nodo, int L, int R) {
    if (L == R)
      stree[nodo].make_Node(arr[L], L);
    else {
      int mid = (L + R) / 2, leftIdx = 2 * nodo, rightIdx = 2 * nodo + 1;
      buildTree(leftIdx, L, mid);
      buildTree(rightIdx, mid + 1, R);
      stree[nodo].merge(stree[leftIdx], stree[rightIdx]);
    }
  }

  void propagate(int nodo, int L, int R) {
    int leftIdx = 2 * nodo, rightIdx = 2 * nodo + 1;
    if (lazy[nodo] != 0) {
      stree[nodo].sum = mod(lazy[nodo] * range(L, R));
      if (L != R) {
        lazy[leftIdx] = lazy[nodo];
        lazy[rightIdx] = lazy[nodo];
      }
      lazy[nodo] = 0;
    }
  }

  Node query(int nodo, int L, int R, int i, int j) {
    propagate(nodo, L, R);
    if (L >= i && R <= j)
      return stree[nodo];

    int mid = (L + R) / 2, leftIdx = 2 * nodo, rightIdx = 2 * nodo + 1;
    if (j <= mid)
      return query(leftIdx, L, mid, i, j);
    if (i > mid)
      return query(rightIdx, mid + 1, R, i, j);

    Node leftResult = query(leftIdx, L, mid, i, mid);
    Node rightResult = query(rightIdx, mid + 1, R, mid + 1, j);
    Node result;
    result.merge(leftResult, rightResult);
    return result;
  }

  void updateRange(int nodo, int low, int high, int startRange, int endRange,
                   ll value) {
    propagate(nodo, low, high);
    if (low > high || startRange > high || endRange < low) {
      return;
    }
    int mid = (low + high) / 2, leftIdx = 2 * nodo, rightIdx = 2 * nodo + 1;
    if (startRange <= low && endRange >= high) {
      stree[nodo].sum = mod(value * range(low, high));
      if (low != high) {
        lazy[leftIdx] = value;
        lazy[rightIdx] = value;
      }
      return;
    }
    updateRange(leftIdx, low, mid, startRange, endRange, value);
    updateRange(rightIdx, mid + 1, high, startRange, endRange, value);
    stree[nodo].merge(stree[leftIdx], stree[rightIdx]);
  }

  int getSegmentTreeSize(int N) {
    int size = 1;
    for (; size < N; size <<= 1)
      ;
    return size << 1;
  }
};

int main() {
  optimizar_io int N, Q, l, r, d;

  cin >> N >> Q;
  acum[0] = 1;
  for (int i = 1; i <= N; i++) {
    acum[i] = mod(acum[i - 1] + powMod(10, i));
  }
  fill(arr, arr + N, 1);
  SegmentTree st(N);
  while (Q--) {
    cin >> l >> r >> d;
    l--;
    r--;
    l = N - l - 1;
    r = N - r - 1;
    if (r < l)
      swap(l, r);
    st.updateRange(1, 0, N - 1, l, r, d);
    Node q = st.query(1, 0, N - 1, 0, N - 1);
    cout << q.getValue() << "\\n";
  }
  return 0;
}

Error: TLE

Fixed submission:

#include <bits/stdc++.h>
using namespace std;
#define MAXN 1000010
#define optimizar_io                                                           \\
  ios_base::sync_with_stdio(false);                                            \\
  cin.tie(0);
typedef long long int ll;

ll arr[MAXN];

ll mod(ll a, ll b = 998244353) { return ((a % b) + b) % b; }

ll powMod(ll a, ll n, ll m = 998244353) {
  ll result = 1;
  while (n) {
    if (n & 1)
      result = mod(result * a, m);
    a = mod(a * a, m);
    n >>= 1;
  }
  return result;
}

ll modInv(ll a, ll n = 998244353) { return powMod(a, n - 2); }

ll geometrica(ll x, ll n) {
  ll ans = powMod(x, n + 1);
  ans--;
  ll inv = modInv(x - 1);
  ll power_sum = mod(ans * inv);
  return power_sum;
}

ll range(int l, int r) {
  if (l == 0)
    return geometrica(10, r);
  else
    return mod(geometrica(10, r) - geometrica(10, l - 1));
}

struct Node {
  ll sum;

  void make_Node(ll v, int idx) { sum = mod(v * powMod(10, idx)); }

  void merge(Node left, Node right) { sum = mod(left.sum + right.sum); }

  ll getValue() { return sum; }
};

struct SegmentTree {

  Node *stree;
  vector<ll> lazy;

  SegmentTree(int N) {
    stree = new Node[getSegmentTreeSize(N)];
    lazy.assign(getSegmentTreeSize(N), 0);
    buildTree(1, 0, N - 1);
  }

  void buildTree(int nodo, int L, int R) {
    if (L == R)
      stree[nodo].make_Node(arr[L], L);
    else {
      int mid = (L + R) / 2, leftIdx = 2 * nodo, rightIdx = 2 * nodo + 1;
      buildTree(leftIdx, L, mid);
      buildTree(rightIdx, mid + 1, R);
      stree[nodo].merge(stree[leftIdx], stree[rightIdx]);
    }
  }

  void propagate(int nodo, int L, int R) {
    int leftIdx = 2 * nodo, rightIdx = 2 * nodo + 1;
    if (lazy[nodo] != 0) {
      stree[nodo].sum = mod(lazy[nodo] * range(L, R));
      if (L != R) {
        lazy[leftIdx] = lazy[nodo];
        lazy[rightIdx] = lazy[nodo];
      }
      lazy[nodo] = 0;
    }
  }

  Node query(int nodo, int L, int R, int i, int j) {
    propagate(nodo, L, R);
    if (L >= i && R <= j)
      return stree[nodo];

    int mid = (L + R) / 2, leftIdx = 2 * nodo, rightIdx = 2 * nodo + 1;
    if (j <= mid)
      return query(leftIdx, L, mid, i, j);
    if (i > mid)
      return query(rightIdx, mid + 1, R, i, j);

    Node leftResult = query(leftIdx, L, mid, i, mid);
    Node rightResult = query(rightIdx, mid + 1, R, mid + 1, j);
    Node result;
    result.merge(leftResult, rightResult);
    return result;
  }

  void updateRange(int nodo, int low, int high, int startRange, int endRange,
                   ll value) {
    propagate(nodo, low, high);
    if (low > high || startRange > high || endRange < low) {
      return;
    }
    int mid = (low + high) / 2, leftIdx = 2 * nodo, rightIdx = 2 * nodo + 1;
    if (startRange <= low && endRange >= high) {
      stree[nodo].sum = mod(value * range(low, high));
      if (low != high) {
        lazy[leftIdx] = value;
        lazy[rightIdx] = value;
      }
      return;
    }
    updateRange(leftIdx, low, mid, startRange, endRange, value);
    updateRange(rightIdx, mid + 1, high, startRange, endRange, value);
    stree[nodo].merge(stree[leftIdx], stree[rightIdx]);
  }

  int getSegmentTreeSize(int N) {
    int size = 1;
    for (; size < N; size <<= 1)
      ;
    return size << 1;
  }
};

int main() {
  int N, Q, l, r, d;
  ll v;

  cin >> N >> Q;
  fill(arr, arr + N, 1);
  SegmentTree st(N);
  while (Q--) {
    cin >> l >> r >> d;
    l--;
    r--;
    l = N - l - 1;
    r = N - r - 1;
    if (r < l)
      swap(l, r);
    st.updateRange(1, 0, N - 1, l, r, d);
    Node q = st.query(1, 0, N - 1, 0, N - 1);
    cout << q.getValue() << "\\n";
  }
  return 0;
}