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

#include <iostream>
#include <utility>
#include <vector>
#define int long long
using namespace std;
const int MAX_N = 1LL << 17, mod = 1000000007LL;

int gcd(int a, int b) {
  if (b > a)
    swap(a, b);
  if (b == 0)
    return a;
  return gcd(b, a % b);
}

int lcm(int a, int b) {
  int d = gcd(a, b);
  return a / d * b;
}

int n;
int dat[2 * MAX_N - 1][2];

void init(int n_) {
  n = 1LL;
  while (n < n_)
    n *= 2LL;
  for (int i = 0; i < 2 * n - 1; ++i) {
    dat[i][0] = 1LL;
  }
}

void update() {
  for (int i = n - 2; i >= 0; --i) {
    int d = gcd(dat[i * 2 + 1][0], dat[i * 2 + 2][0]);
    dat[i][0] = dat[i * 2 + 1][0] / d * dat[i * 2 + 2][0];
    dat[i][1] = (((dat[i * 2 + 2][0] / d) % mod * dat[i * 2 + 1][1]) % mod +
                 ((dat[i * 2 + 1][0] / d) % mod * dat[i * 2 + 2][1]) % mod) %
                mod;
  }
}

//[a, b)???lcm??¨ret??????????±??????????
pair<int, int> query(int a, int b, int k, int l, int r) {
  if (r <= a || b <= l)
    return make_pair(1LL, 0LL);
  if (a <= l && r <= b)
    return make_pair(dat[k][0], dat[k][1]);
  else {
    pair<int, int> vl = query(a, b, k * 2 + 1, l, (l + r) / 2);
    pair<int, int> vr = query(a, b, k * 2 + 2, (l + r) / 2, r);
    int d = gcd(vl.first, vr.first);
    int c = ((vr.first / d) % mod * vl.second % mod +
             (vl.first / d) % mod * vr.second % mod) %
            mod;
    return make_pair(vl.first / d * vr.first, c);
  }
}

signed main() {
  int N, Q;
  cin >> N >> Q;
  int P[N];
  for (int i = 0; i < N; ++i) {
    cin >> P[i];
    --P[i];
  }
  init(N);
  for (int i = 0; i < N; ++i) {
    int cur = P[i], t = 1, c = (i + 1) % mod;
    while (cur != i) { //??¶?´??????????40?????\\?????§??¢??????
      c += (cur + 1) % mod;
      c %= mod;
      cur = P[cur];
      ++t;
    }
    dat[i + n - 1][0] = t;
    dat[i + n - 1][1] = c;
  }
  update();
  int l, r;
  for (int i = 0; i < Q; ++i) {
    cin >> l >> r;
    --l;
    cout << query(l, r, 0, 0, n).second % mod << endl;
  }
  return 0;
}

/*
int main(){
  int N, Q;
  cin >> N >> Q;
  int P[N];
  for(int i = 0; i < N; ++i){
    cin >> P[i];
    --P[i];
  }
  int LCM[N+1], GCD[N+1], T[N], C[N];
  for(int i = 0; i < N; ++i){
    int cur = P[i], t = 1, c = (i+1)%mod;
    while(cur != i){//??¶?´??????????40?????\\?????§??¢??????
      c += (cur + 1)%mod;
      cur = P[cur];
      ++t;
    }
    T[i] = t;
    C[i] = c;
  }
  GCD[0] = T[0];
  LCM[0] = T[0];
  for(int i = 0; i < N-1; ++i){
    GCD[i+1] = gcd(GCD[i],T[i+1]);
    LCM[i+1] = lcm(LCM[i],T[i+1]);
  }
  int C_[N];
  C_[0] = C[0];
  for(int i = 1; i < N; ++i){
    C_[i] = LCM[i]/GCD[i]*C[i] + LCM[i]/LCM[i-1]*C_[i-1];
  }
  for(int i = 0; i < N; ++i){
    cout << C_[i] << " ";
  }cout << endl;

  int l, r;
  for(int i = 0; i < Q; ++i){
    cin >> l >> r;
    --l;--r;
    int ans, k;
    if(l == 0){
      k = LCM[r]*GCD[r];
      ans = C_[r]/LCM[r]*k - C_[l]/LCM[l]*k;
    }else{
      k = LCM[r]/LCM[l-1]*GCD[r];
      ans = C_[r]/LCM[r]*k - C_[l]/LCM[l]*k;
    }
    ans %= mod;
    cout << ans << endl;
  }

  return 0;
}
*/

Error: TLE

Fixed submission:

#include <iostream>
#include <utility>
#include <vector>
using namespace std;
const int MAX_N = 1 << 17, mod = 1000000007;

int gcd(int a, int b) {
  if (b > a)
    swap(a, b);
  if (b == 0)
    return a;
  return gcd(b, a % b);
}

int lcm(int a, int b) {
  int d = gcd(a, b);
  return a / d * b;
}

int n;
int dat[2 * MAX_N - 1][2];

void init(int n_) {
  n = 1;
  while (n < n_)
    n *= 2;
  for (int i = 0; i < 2 * n - 1; ++i) {
    dat[i][0] = 1;
  }
}

void update(int N) {
  for (int i = n - 2; i >= 0; --i) {
    int m = lcm(dat[i * 2 + 1][0], dat[i * 2 + 2][0]);
    dat[i][0] = m;
    dat[i][1] = (m / dat[i * 2 + 1][0] * dat[i * 2 + 1][1] % mod +
                 m / dat[i * 2 + 2][0] * dat[i * 2 + 2][1] % mod) %
                mod;
  }
}

//[a,
//b)テ」ツ?ョlcmテ」ツ?ィretテ」ツ?ョテ・ツ?、テ」ツつ津ヲツアツづ」ツつ?」ツつ凝」ツ??
pair<int, int> query(int a, int b, int k, int l, int r) {
  if (r <= a || b <= l)
    return make_pair(1, 0);
  if (a <= l && r <= b)
    return make_pair(dat[k][0], dat[k][1]);
  else {
    pair<int, int> vl = query(a, b, k * 2 + 1, l, (l + r) / 2);
    pair<int, int> vr = query(a, b, k * 2 + 2, (l + r) / 2, r);
    int m = lcm(vl.first, vr.first);
    int c =
        (m / vl.first * vl.second % mod + m / vr.first * vr.second % mod) % mod;
    return make_pair(m, c);
  }
}

int main() {
  int N, Q;
  cin >> N >> Q;
  int P[N];
  for (int i = 0; i < N; ++i) {
    cin >> P[i];
    --P[i];
  }
  init(N);
  for (int i = 0; i < N; ++i) {
    int cur = P[i], t = 1, c = i + 1;
    while (
        cur !=
        i) { // テ・ツ按カテァツエツ?」ツ?凝」ツつ嘉」ツ??0テ・ツ崢榲、ツサツ・テ、ツクツ凝」ツ?ァテヲツュツ「テ」ツ?セテ」ツつ?
      c += cur + 1;
      cur = P[cur];
      ++t;
    }
    dat[i + n - 1][0] = t;
    dat[i + n - 1][1] = c;
  }
  update(N);
  int l, r;
  for (int i = 0; i < Q; ++i) {
    cin >> l >> r;
    --l;
    cout << query(l, r, 0, 0, n).second << endl;
  }
  return 0;
}