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

#include <algorithm>
#include <cmath>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>
using namespace std;
typedef long long ll;
#define fi first
#define se second
#define mp make_pair
#define mt make_tuple
#define pqueue priority_queue
const int inf = 1e9 + 7;
const ll mod = 1e9 + 7;
const ll mod1 = 998244353;
const ll big = 1e18;
const double PI = 2 * asin(1);

int N;
ll twopow[20], tenpow[1000000], ninepow;

ll mypow(ll a, ll b) {
  ll tmp;
  ll two;
  ll ans = 1;
  while (b > 0) {
    two = 1;
    tmp = a;
    while (2 * two < b) {
      two *= 2;
      tmp *= tmp;
      tmp %= mod1;
    }
    b -= two;
    ans *= tmp;
    ans %= mod1;
  }
  return ans;
}

struct SegmentTree {
  vector<pair<ll, ll>> Tree[20];

  void init() {
    for (int i = 0; i < 20; ++i) {
      Tree[i].resize((1 << i));
    }
    for (int i = 0; i < N; ++i)
      Tree[19][i] = mp(1, 0);
    ll ten = 10;
    for (int pos1 = 18; pos1 >= 0; --pos1) {
      for (int pos2 = 0; pos2 < Tree[pos1].size(); ++pos2) {
        Tree[pos1][pos2].fi = (Tree[pos1 + 1][2 * pos2].fi * ten % mod1 +
                               Tree[pos1 + 1][2 * pos2 + 1].fi) %
                              mod1;
      }
      ten *= ten;
      ten %= mod1;
    }
  }

  void eval(int pos1, int pos2) {
    if (Tree[pos1][pos2].se == 0)
      return;
    if (pos1 + 1 < 20) {
      Tree[pos1 + 1][2 * pos2].se = Tree[pos1][pos2].se;
      Tree[pos1 + 1][2 * pos2 + 1].se = Tree[pos1][pos2].se;
    }
    ll len = twopow[19 - pos1];
    Tree[pos1][pos2].fi =
        Tree[pos1][pos2].se * (tenpow[len] - 1) % mod1 * ninepow % mod1;
    Tree[pos1][pos2].se = 0;
  }

  void update(int ql, int qr, ll D, int pos1 = 0, int pos2 = 0, ll sl = 0,
              ll sr = (1 << 19)) {
    eval(pos1, pos2);
    if (qr <= sl || sr <= ql)
      return;
    if (ql <= sl && sr <= qr) {
      Tree[pos1][pos2].se = D;
      eval(pos1, pos2);
      return;
    }
    update(ql, qr, D, pos1 + 1, 2 * pos2, sl, (sl + sr) / 2);
    update(ql, qr, D, pos1 + 1, 2 * pos2 + 1, (sl + sr) / 2, sr);
    ll len = twopow[20 - pos1 - 2];
    ll ten = tenpow[len];
    Tree[pos1][pos2].fi = (Tree[pos1 + 1][2 * pos2].fi * ten % mod1 +
                           Tree[pos1 + 1][2 * pos2 + 1].fi) %
                          mod1;
    return;
  }

  ll find(int ql, int qr, int pos1 = 0, int pos2 = 0, int sl = 0,
          int sr = (1 << 19)) {
    eval(pos1, pos2);
    if (qr <= sl || sr <= ql)
      return 0;
    if (ql <= sl && sr <= qr)
      return (Tree[pos1][pos2].fi * tenpow[N - sr]) % mod1;
    return (find(ql, qr, pos1 + 1, 2 * pos2, sl, (sl + sr) / 2) +
            find(ql, qr, pos1 + 1, 2 * pos2 + 1, (sl + sr) / 2, sr)) %
           mod1;
  }

  void check() {
    for (int i = 16; i < 20; ++i) {
      for (int j = 0; j < (1 << (i - 16)); ++j) {
        cout << "(" << Tree[i][j].fi << "," << Tree[i][j].se << ")"
             << " ";
      }
      cout << endl;
    }
  }
};

int main() {
  for (int i = 0; i < 20; ++i)
    twopow[i] = mypow(2, i);
  for (int i = 0; i < 1000000; ++i)
    tenpow[i] = mypow(10, i);
  ninepow = mypow(9, mod1 - 2);
  int Q;
  cin >> N >> Q;
  SegmentTree tree;
  tree.init();
  ll ans[Q];
  ll L, R, D;
  for (int i = 0; i < Q; ++i) {
    cin >> L >> R >> D;
    L--;
    tree.update(L, R, D);
    ans[i] = tree.find(0, N);
  }
  for (int i = 0; i < Q; ++i)
    cout << ans[i] << endl;
}


Error: TLE

Fixed submission:

#include <algorithm>
#include <cmath>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>
using namespace std;
typedef long long ll;
#define fi first
#define se second
#define mp make_pair
#define mt make_tuple
#define pqueue priority_queue
const int inf = 1e9 + 7;
const ll mod = 1e9 + 7;
const ll mod1 = 998244353;
const ll big = 1e18;
const double PI = 2 * asin(1);

int N;
ll twopow[20], tenpow[200005], ninepow;

ll mypow(ll a, ll b) {
  ll tmp;
  ll two;
  ll ans = 1;
  while (b > 0) {
    two = 1;
    tmp = a;
    while (2 * two < b) {
      two *= 2;
      tmp *= tmp;
      tmp %= mod1;
    }
    b -= two;
    ans *= tmp;
    ans %= mod1;
  }
  return ans;
}

struct SegmentTree {
  vector<pair<ll, ll>> Tree[20];

  void init() {
    for (int i = 0; i < 20; ++i) {
      Tree[i].resize((1 << i));
    }
    for (int i = 0; i < N; ++i)
      Tree[19][i] = mp(1, 0);
    ll ten = 10;
    for (int pos1 = 18; pos1 >= 0; --pos1) {
      for (int pos2 = 0; pos2 < Tree[pos1].size(); ++pos2) {
        Tree[pos1][pos2].fi = (Tree[pos1 + 1][2 * pos2].fi * ten % mod1 +
                               Tree[pos1 + 1][2 * pos2 + 1].fi) %
                              mod1;
      }
      ten *= ten;
      ten %= mod1;
    }
  }

  void eval(int pos1, int pos2) {
    if (Tree[pos1][pos2].se == 0)
      return;
    if (pos1 + 1 < 20) {
      Tree[pos1 + 1][2 * pos2].se = Tree[pos1][pos2].se;
      Tree[pos1 + 1][2 * pos2 + 1].se = Tree[pos1][pos2].se;
    }
    ll len = twopow[19 - pos1];
    Tree[pos1][pos2].fi =
        Tree[pos1][pos2].se * (mypow(10, len) - 1) % mod1 * ninepow % mod1;
    Tree[pos1][pos2].se = 0;
  }

  void update(int ql, int qr, ll D, int pos1 = 0, int pos2 = 0, ll sl = 0,
              ll sr = (1 << 19)) {
    eval(pos1, pos2);
    if (qr <= sl || sr <= ql)
      return;
    if (ql <= sl && sr <= qr) {
      Tree[pos1][pos2].se = D;
      eval(pos1, pos2);
      return;
    }
    update(ql, qr, D, pos1 + 1, 2 * pos2, sl, (sl + sr) / 2);
    update(ql, qr, D, pos1 + 1, 2 * pos2 + 1, (sl + sr) / 2, sr);
    ll len = twopow[20 - pos1 - 2];
    ll ten = mypow(10, len);
    Tree[pos1][pos2].fi = (Tree[pos1 + 1][2 * pos2].fi * ten % mod1 +
                           Tree[pos1 + 1][2 * pos2 + 1].fi) %
                          mod1;
    return;
  }

  ll find(int ql, int qr, int pos1 = 0, int pos2 = 0, int sl = 0,
          int sr = (1 << 19)) {
    eval(pos1, pos2);
    if (qr <= sl || sr <= ql)
      return 0;
    if (ql <= sl && sr <= qr)
      return (Tree[pos1][pos2].fi * mypow(10, N - sr)) % mod1;
    return (find(ql, qr, pos1 + 1, 2 * pos2, sl, (sl + sr) / 2) +
            find(ql, qr, pos1 + 1, 2 * pos2 + 1, (sl + sr) / 2, sr)) %
           mod1;
  }

  void check() {
    for (int i = 16; i < 20; ++i) {
      for (int j = 0; j < (1 << (i - 16)); ++j) {
        cout << "(" << Tree[i][j].fi << "," << Tree[i][j].se << ")"
             << " ";
      }
      cout << endl;
    }
  }
};

int main() {
  for (int i = 0; i < 20; ++i)
    twopow[i] = mypow(2, i);
  for (int i = 0; i < 200005; ++i)
    tenpow[i] = mypow(10, i);
  ninepow = mypow(9, mod1 - 2);
  int Q;
  cin >> N >> Q;
  SegmentTree tree;
  tree.init();
  ll ans[Q];
  ll L, R, D;
  for (int i = 0; i < Q; ++i) {
    cin >> L >> R >> D;
    L--;
    tree.update(L, R, D);
    ans[i] = tree.find(0, N);
  }
  for (int i = 0; i < Q; ++i)
    cout << ans[i] << endl;
}