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

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

typedef long long ll;
const ll M = 1e9 + 7;
const int MAX_K = 50;
const int MAX_N = 100100;
const int LOG_N = 20;

int N, Q;
vector<int> P;
ll table[MAX_K][MAX_N];
ll cumlt[MAX_N];
ll imos[MAX_N + 1];
ll stable[LOG_N][MAX_N];

ll lcm(ll a, ll b) { return a / __gcd(a, b) * b; }

ll extgcd(ll a, ll b, ll &x, ll &y) {
  ll g = a;
  x = 1;
  y = 0;
  if (b != 0)
    g = extgcd(b, a % b, y, x), y -= (a / b) * x;
  return g;
}
ll inv(ll a) {
  ll x, y;
  if (extgcd(a, M, x, y) == 1)
    return (x + M) % M;
  else
    return 0; // unsolvable
}

ll query(int l, int r) {
  int n = r - l;
  int i = sizeof(n) * 8 - __builtin_clz(n) - 1;
  return lcm(stable[i][l], stable[i][r - (1 << i)]);
}

int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);

  cin >> N >> Q;
  P.resize(N);
  for (int i = 0; i < N; i++) {
    int v;
    cin >> v, v--;
    P[v] = i;
  }

  for (int i = 0; i < N; i++)
    table[0][i] = i + 1;
  for (int i = 1; i < MAX_K; i++)
    for (int j = 0; j < N; j++)
      table[i][P[j]] = table[i - 1][j];

  vector<ll> cycle(N);
  for (int i = 0; i < N; i++) {
    for (int j = 1; j < MAX_K; j++) {
      cumlt[i] = (table[j][i] + cumlt[i]) % M;
      if (table[j][i] == i + 1) {
        cycle[i] = j;
        break;
      }
    }
  }

  for (int i = 0; i < N; i++)
    stable[0][i] = cycle[i];
  for (int i = 1; i < LOG_N; i++) {
    for (int j = 0; j < N; j++) {
      if (N <= j + (1 << (i - 1)) || stable[i - 1][j + (1 << (i - 1))] == 0)
        break;
      stable[i][j] = lcm(stable[i - 1][j], stable[i - 1][j + (1 << (i - 1))]);
    }
  }

  for (int i = 0; i < N; i++)
    imos[i + 1] = (imos[i] + (cumlt[i] * inv(cycle[i])) % M) % M;

  while (Q--) {
    int L, R;
    cin >> L >> R, L--;

    ll x = query(L, R) % M;
    ll ans = ((imos[R] - imos[L] + M) % M * x) % M;

    cout << ans << endl;
  }

  return 0;
}

Error: TLE

Fixed submission:

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

typedef long long ll;
const ll M = 1e9 + 7;
const int MAX_K = 50;
const int MAX_N = 100100;

int N, Q;
vector<int> P;
ll table[MAX_K][MAX_N];
ll cumlt[MAX_N];

ll gcd(ll a, ll b) {
  if (b == 0)
    return a;
  return gcd(b, a % b);
}

ll lcm(ll a, ll b) { return a / gcd(a, b) * b; }

class SegmentTree {
public:
  int n;
  vector<ll> data;

  SegmentTree(int _n) {
    n = 1;
    while (n < _n)
      n *= 2;
    data.resize(2 * n - 1, 1);
  };

  void update(int k, ll a) {
    k += n - 1;
    data[k] = a;
    while (k > 0) {
      k = (k - 1) / 2;
      data[k] = lcm(data[k * 2 + 1], data[k * 2 + 2]);
    }
  }

  ll query(int a, int b, int k, int l, int r) {
    if (r <= a || b <= l)
      return 1;

    if (a <= l && r <= b)
      return data[k];
    else {
      int mid = (l + r) / 2;
      ll x = query(a, b, k * 2 + 1, l, mid);
      ll y = query(a, b, k * 2 + 2, mid, r);
      return lcm(x, y);
    }
  }
  ll query(int a, int b) { return query(a, b, 0, 0, n); }
};

int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);

  cin >> N >> Q;
  P.resize(N);
  for (int i = 0; i < N; i++) {
    int v;
    cin >> v, v--;
    P[v] = i;
  }

  for (int i = 0; i < N; i++)
    table[0][i] = i + 1;
  for (int i = 1; i < MAX_K; i++)
    for (int j = 0; j < N; j++)
      table[i][P[j]] = table[i - 1][j];

  vector<ll> cycle(N);
  for (int i = 0; i < N; i++) {
    for (int j = 1; j < MAX_K; j++) {
      cumlt[i] = (table[j][i] + cumlt[i]) % M;
      if (table[j][i] == i + 1) {
        cycle[i] = j;
        break;
      }
    }
  }

  SegmentTree st(N);
  for (int i = 0; i < N; i++)
    st.update(i, cycle[i]);

  while (Q--) {
    int L, R;
    cin >> L >> R, L--;

    ll x = st.query(L, R);
    ll ans = 0;
    for (int i = L; i < R; i++)
      ans = (ans + ((x / cycle[i]) % M * cumlt[i]) % M) % M;

    cout << ans << endl;
  }

  return 0;
}