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

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

const bool ready = []() {
  ios_base::sync_with_stdio(false);
  cin.tie(0);
  cout << fixed << setprecision(12);
  return true;
}();

const double PI = acos(-1);
using ll = long long;
#define int ll
#define all(v) (v).begin(), (v).end()
#define fori(n) for (int i = 0; i < int(n); i++)

#define cini(i)                                                                \\
  int i;                                                                       \\
  cin >> i;
#define cins(s)                                                                \\
  string s;                                                                    \\
  cin >> s;
#define cind(d)                                                                \\
  double d;                                                                    \\
  cin >> d;
#define cinai(a, n)                                                            \\
  vi a(n);                                                                     \\
  fori(n) { cin >> a[i]; }
#define cinas(s, n)                                                            \\
  vs s(n);                                                                     \\
  fori(n) { cin >> s[i]; }
#define cinad(a, n)                                                            \\
  vd a(n);                                                                     \\
  fori(n) { cin >> a[i]; }

using pii = pair<int, int>;
using pdd = pair<double, double>;
using vd = vector<double>;
using vb = vector<bool>;
using vi = vector<int>;
using vvi = vector<vi>;
using vs = vector<string>;

#define endl "\\n"

template <typename E> struct SegmentTreeLazy {
  vector<E> data;
  vector<E> lazySet;
  vector<bool> lazySetB; /* flag if there is a pending lazySet in node */

  E neutral;
  int n;

  function<E(E, E)> plus;
  function<E(E, int, int)> mult2;

  SegmentTreeLazy(int _n, E _neutral) {
    n = 1;
    while (n < _n)
      n *= 2;

    data.resize(n * 2, _neutral);
    lazySet.resize(n * 2, _neutral);
    lazySetB.resize(n * 2);
    neutral = _neutral;
  }

  /* bulk update in O(n) */
  template <typename Iterator> void init(Iterator beg, Iterator end) {
    for (int idx = n; beg != end; beg++, idx++)
      data[idx] = *beg;

    for (int idx = n - 1; idx >= 1; idx--)
      data[idx] = plus(data[idx * 2], data[idx * 2 + 1]);
  }

  /* pushes down the pending updates to the vertex node
   * If both lazies are set then the inc was later, so both
   * have to be pushed.
   * But first the set, which erases all previously set
   * and inc on the child nodes, then the inc.
   * */
  void pushlazy(int node, int sL, int sR) {
    if (lazySetB[node]) {
      // cerr<<"pushlazy Set, node="<<node<<" sL="<<sL<<" sR="<<sR<<endl;

      if (sL != sR) {
        int mid = (sL + sR) / 2;
        rangeSet(node * 2, sL, mid, sL, mid, lazySet[node]);
        rangeSet(node * 2 + 1, mid + 1, sR, mid + 1, sR, lazySet[node]);
      }

      lazySetB[node] = false;
      lazySet[node] = neutral;
    }
  }

  /* @return accumulative (l,r), both inclusive, top down */
  E query(int node, int sL, int sR, int l, int r) {
    if (r < sL || l > sR)
      return neutral;
    // cerr<<"query, node="<<node<<" sL="<<sL<<" sR="<<sR<<" l="<<l<<" r="<<r<<"
    // data[node]="<<data[node]<<endl;

    if (l <= sL && r >= sR)
      return data[node];

    pushlazy(node, sL, sR);

    int mid = (sL + sR) / 2;
    return plus(query(node * 2, sL, mid, l, r),
                query(node * 2 + 1, mid + 1, sR, l, r));
  }
  E query(int l, int r) { return query(1, 0, n - 1, l, r); }

  /* set all position in (l,r) to val */
  void rangeSet(int node, int sL, int sR, int l, int r, E val) {
    if (r < sL || l > sR)
      return;
    // cerr<<"rangeSet node="<<node<<" sL="<<sL<<" sR="<<sR<<" l="<<l<<"
    // r="<<r<<" val="<<val<<endl;

    if (l <= sL && r >= sR) {
      lazySet[node] = val;
      lazySetB[node] = true;
      data[node] = mult2(val, sL, sR);
      // cerr<<"rangeSet did set node="<<data[node]<<endl;
      return;
    }

    pushlazy(node, sL, sR);

    int mid = (sL + sR) / 2;
    rangeSet(node * 2, sL, mid, l, r, val);
    rangeSet(node * 2 + 1, mid + 1, sR, l, r, val);
    data[node] = plus(data[node * 2], data[node * 2 + 1]);
  }

  /* set val at positions (l,r) */
  void rangeSet(int l, int r, E val) { rangeSet(1, 0, n - 1, l, r, val); }
};

const int MOD = 998244353;

int mul(const int v1, const int v2, int mod = MOD) {
  return (int)((1LL * v1 * v2) % mod);
}

int pl(int v1, int v2, int mod = MOD) {
  int res = v1 + v2;

  while (res < 0)
    res += mod;

  while (res >= mod)
    res -= mod;

  return res;
}

/*
 * SegmentTree, lazy updates.
 *
 * But the update-function is complecated :/
 * We need to consider the sum of the pows of the positions...somehow.
 *
 */
void solve() {
  cini(n);
  cini(q);

  vi ten(n);
  vi pten(n + 1); /* prefix sums of ten[] */
  ten[0] = 1;
  pten[1] = ten[0];
  for (int i = 1; i < n; i++) {
    ten[i] = mul(ten[i - 1], 10);
    pten[i + 1] = pl(pten[i], ten[i]);
  }

  SegmentTreeLazy<int> seg(n, 0);
  seg.plus = [](int i1, int i2) { return (i1 + i2) % MOD; };
  seg.mult2 = [&](int v, int l, int r) {
    return mul(pl(pten[r + 1], -pten[l]), v);
  };

  seg.rangeSet(0, n - 1, 1);

  for (int i = 0; i < q; i++) {
    cini(l);
    l--;
    cini(r);
    r--;
    cini(d);
    seg.rangeSet(n - 1 - r, n - 1 - l, d);
    cout << seg.query(0, n - 1) << endl;
  }
}

signed main() { solve(); }

Error: TLE

Fixed submission:

// Author : Sarthak Kapoor
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
using namespace std;
using namespace __gnu_pbds;
#define int ll
#define rep(i, n) for (int i = 0; i < n; ++i)
#define repa(i, a, n) for (int i = a; i < n; ++i)
#define repr(i, n) for (int i = n - 1; i >= 0; --i)
#define ll long long
#define pi pair<int, int>
#define pii pair<pi, int>
#define vi vector<int>
#define pb push_back
#define fi first
#define sec second
#define all(v) v.begin(), v.end()
// #define s(v) v.size()
ll mod = 998244353;
mt19937 rng(chrono::steady_clock::now()
                .time_since_epoch()
                .count()); // use rng()%n for numbers in range [0,n-1]
ll gcd(ll a, ll b) {
  if (b == 0)
    return a;
  return gcd(b, a % b);
}
ll fastexp(ll x, ll a) {
  ll res = 1;
  while (a > 0) {
    if (a & 1) {
      res = (res * x) % mod;
    }
    a = a >> 1;
    x = (x * x) % mod;
  }
  return res;
}
ll inverse(ll n) { return fastexp(n, mod - 2); }
template <typename T> void add(T &a, T b) {
  a += b;
  if (a >= mod)
    a -= mod;
}
template <typename T> void sub(T &a, T b) {
  a -= b;
  if (a < 0)
    a += mod;
}
template <typename T> void mul(T &a, T b) {
  a *= b;
  if (a >= mod)
    a %= mod;
}
const int maxn = 2e5 + 10;
int n;
vi s(4 * maxn);
vi a(maxn);
vi lazy(4 * maxn, -1);
vi pows(maxn);
void push(int id, int l, int mid, int r) {
  if (lazy[id] == -1)
    return;
  lazy[2 * id] = lazy[id];
  lazy[2 * id + 1] = lazy[id];
  // s[2*id] = lazy[id];
  int t = mid - l;
  int val = lazy[id];
  int temp = pows[t];
  sub(temp, 1ll);
  mul(temp, inverse(9));
  mul(temp, val);
  s[2 * id] = temp;
  t = r - mid;
  // int t = mid-l;
  temp = pows[t];
  sub(temp, 1ll);
  mul(temp, inverse(9));
  mul(temp, val);
  s[2 * id + 1] = temp;
  // s[2*id+1] = lazy[id];
  lazy[id] = -1;
}
void build(int id = 1, int l = 0, int r = n) {
  if (r - l < 2) {
    s[id] = 1;
    return;
  }
  int mid = (l + r) / 2;
  build(2 * id, l, mid);
  build(2 * id + 1, mid, r);
  int temp = s[2 * id];
  mul(temp, pows[r - mid]);
  add(temp, s[2 * id + 1]);
  s[id] = temp;
  // s[id] = s[2*id]+s[2*id+1];
}
int sum(int x, int y, int id = 1, int l = 0, int r = n) {
  if (x >= r || l >= y) {
    return 0;
  }
  if (x <= l && r <= y) {
    return s[id];
  }
  int mid = (l + r) / 2;
  push(id, l, mid, r);
  int temp = sum(x, y, 2 * id, l, mid);
  mul(temp, pows[r - mid]);
  add(temp, sum(x, y, 2 * id + 1, mid, r));
  return temp;
}
void update(int x, int y, int val, int id = 1, int l = 0, int r = n) {
  if (x >= r || l >= y) {
    return;
  }
  if (x <= l && r <= y) {
    lazy[id] = val;
    int t = r - l;
    int temp = pows[t];
    sub(temp, 1ll);
    mul(temp, inverse(9));
    mul(temp, val);
    s[id] = temp;
    // s[id] =
    // s[id] = val*(r-l);
    return;
  }
  int mid = (l + r) / 2;
  push(id, l, mid, r);
  update(x, y, val, 2 * id, l, mid);
  update(x, y, val, 2 * id + 1, mid, r);
  int temp = s[2 * id];
  mul(temp, pows[r - mid]);
  add(temp, s[2 * id + 1]);
  s[id] = temp;
  // s[id] = s[2*id] + s[2*id+1];
}
signed main() {
  ios::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  int q;
  cin >> n >> q;
  pows[0] = 1;
  repa(i, 1, maxn) {
    pows[i] = pows[i - 1] * 10;
    pows[i] %= mod;
  }
  build();
  // int ans = sum(0,n);
  // cout<<ans<<"\\n";
  // rep(i,n){
  // 	cout<<sum(i,i+1)<<"\\n";
  // }
  // cout<<sum(0,n)<<"\\n";
  rep(i, q) {
    int l, r, d;
    cin >> l >> r >> d;
    update(l - 1, r, d);
    // int temp = sum(l-1,r);
    // sub(ans,temp);
    // int t = r-l+1;
    // temp = pows[t];
    // sub(temp,1ll);
    // mul(temp,inverse(9));
    // mul(temp,d);
    // mul(temp,pows[n-r]);
    // add(ans,temp);
    // cout<<ans<<"\\n";
    // mul(temp,inverse(pows[l-1]));
    cout << sum(0, n) << "\\n";
  }
  return 0;
}