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

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

long long gcd(long long a, long long b) { return b ? gcd(b, a % b) : a; }
long long lcm(long long a, long long b) { return a / gcd(a, b) * b; }

long long mul(long long a, long long b, const long long mod) {
  return b ? (mul(a * 2, b / 2, mod) + (b & 1 ? a : 0)) % mod : 0;
}

long long bpow(long long a, long long b, const long long mod) {
  return (b ? bpow(a * a % mod, b / 2, mod) * (b & 1 ? a : 1) : 1) % mod;
}

long long inv(long long a, const long long mod) {
  return bpow(a, mod - 2, mod);
}

// to overflow
/*long long bpow(long long a,long long b,const long long mod){
        return (b?mul(bpow(mul(a,a,mod),b/2,mod),(b&1?a:1),mod):1)%mod;
}*/
class mInt {
public:
  static const long long mod = 1000000007;
  long long v;
  mInt() : v(0) {}
  mInt(long long v) : v((v % mod + mod) % mod) {}
};
mInt &operator+=(mInt &a, mInt b) { return a = a.v + b.v; }
mInt &operator-=(mInt &a, mInt b) { return a = a.v - b.v; }
mInt &operator*=(mInt &a, mInt b) { return a = a.v * b.v; }
mInt &operator/=(mInt &a, mInt b) { return a = a.v * inv(b.v, mInt::mod); }
mInt operator+(mInt a, mInt b) { return a += b; }
mInt operator-(mInt a, mInt b) { return a -= b; }
mInt operator*(mInt a, mInt b) { return a *= b; }
mInt operator/(mInt a, mInt b) { return a /= b; }
ostream &operator<<(ostream &os, const mInt &x) { return os << x.v; }

int p[100010];
int done[100010];
vector<int> v;
int len = 0;
int dfs(int x) {
  if (done[x]++)
    return 0;
  v.push_back(x);
  len++;
  dfs(p[x]);
}

template <class T> struct SegmentTree {
  int n_;
  vector<T> seg;
  // [1,N]
  SegmentTree(int N) {
    n_ = 1;
    while (n_ < N)
      n_ *= 2;
    seg.resize(2 * n_, 1); //????¨????
  }
  void add(int i, int v) {
    i += n_ - 1;
    seg[i] = v;
    i /= 2;
    while (i) {
      seg[i] = lcm(seg[i * 2], seg[i * 2 + 1]); //????¨????
      i /= 2;
    }
  }
  T get(int l, int r, int k, int a, int b) {
    if (b < l || r < a)
      return 1; //????¨????
    if (l <= a && b <= r) {
      return seg[k];
    }
    int m = (a + b) / 2;
    return lcm(get(l, r, k * 2, a, m),
               get(l, r, k * 2 + 1, m + 1, b)); //????¨????
  }
  inline T get(int l, int r) { return get(l, r, 1, 1, n_); }
};
template <class T> struct SegmentTree2 {
  int n_;
  vector<T> seg;
  // [1,N]
  SegmentTree2(int N) {
    n_ = 1;
    while (n_ < N)
      n_ *= 2;
    seg.resize(2 * n_, 1); //????¨????
  }
  void add(int i, int v) {
    i += n_ - 1;
    seg[i] = v;
    i /= 2;
    while (i) {
      seg[i] = max(seg[i * 2], seg[i * 2 + 1]); //????¨????
      i /= 2;
    }
  }
  T get(int l, int r, int k, int a, int b) {
    if (b < l || r < a)
      return 1; //????¨????
    if (l <= a && b <= r) {
      return seg[k];
    }
    int m = (a + b) / 2;
    return max(get(l, r, k * 2, a, m),
               get(l, r, k * 2 + 1, m + 1, b)); //????¨????
  }
  inline T get(int l, int r) { return get(l, r, 1, 1, n_); }
};

struct BIT {
  vector<mInt> seg;
  // [1,n]
  BIT(int N) { seg.resize(N + 1, mInt(0)); };
  void add(int i, mInt x) { seg[i] = seg[i] + x; }
  void init() {
    for (int i = 1; i < seg.size(); i++) {
      seg[i] += seg[i - 1];
    }
  }
  inline mInt get(int l, int r) { return (seg[r] - seg[l - 1]); }
};

int main() {
  int N, Q;
  cin >> N >> Q;
  for (int i = 1; i <= N; i++) {
    scanf("%d", &p[i]);
  }

  SegmentTree<long long> LCM(N);
  BIT bit1(N);

  for (int i = 1; i <= N; i++) {
    if (done[i])
      continue;
    len = 0;
    v.clear();
    dfs(i);
    mInt sum = 0;
    for (int j = 0; j < v.size(); j++) {
      sum += v[j];
      LCM.add(v[j], len);
    }
    for (int j = 0; j < v.size(); j++) {
      bit1.add(v[j], sum / len);
    }
  }
  bit1.init();
  for (int i = 0; i < Q; i++) {
    mInt ans = 0;
    long long l, r;
    cin >> l >> r;
    mInt len = LCM.get(l, r);
    ans += len * bit1.get(l, r);

    printf("%d\\n", (int)ans.v);
  }
}

Error: TLE

Fixed submission:

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

int p[100010];
int done[100010];
vector<int> v;
int len = 0;
int dfs(int x) {
  if (done[x]++)
    return 0;
  v.push_back(x);
  len++;
  dfs(p[x]);
}

#define lcm(a, b) (a / __gcd(a, b) * b)
template <class T> struct SegmentTree {
  int n_;
  vector<T> seg;
  // [1,N]
  SegmentTree(int N) {
    n_ = 1;
    while (n_ < N)
      n_ *= 2;
    seg.resize(2 * n_, 1); //????¨????
  }
  void add(int i, int v) {
    i += n_ - 1;
    seg[i] = v;
    i /= 2;
    while (i) {
      seg[i] = lcm(seg[i * 2], seg[i * 2 + 1]); //????¨????
      i /= 2;
    }
  }
  T get(int l, int r, int k, int a, int b) {
    if (b < l || r < a)
      return 1; //????¨????
    if (l <= a && b <= r) {
      return seg[k];
    }
    int m = (a + b) / 2;
    return lcm(get(l, r, k * 2, a, m),
               get(l, r, k * 2 + 1, m + 1, b)); //????¨????
  }
  inline T get(int l, int r) { return get(l, r, 1, 1, n_); }
};
template <class T> struct SegmentTree2 {
  int n_;
  vector<T> seg;
  // [1,N]
  SegmentTree2(int N) {
    n_ = 1;
    while (n_ < N)
      n_ *= 2;
    seg.resize(2 * n_, 1); //????¨????
  }
  void add(int i, int v) {
    i += n_ - 1;
    seg[i] = v;
    i /= 2;
    while (i) {
      seg[i] = max(seg[i * 2], seg[i * 2 + 1]); //????¨????
      i /= 2;
    }
  }
  T get(int l, int r, int k, int a, int b) {
    if (b < l || r < a)
      return 1; //????¨????
    if (l <= a && b <= r) {
      return seg[k];
    }
    int m = (a + b) / 2;
    return max(get(l, r, k * 2, a, m),
               get(l, r, k * 2 + 1, m + 1, b)); //????¨????
  }
  inline T get(int l, int r) { return get(l, r, 1, 1, n_); }
};

struct BIT {
  vector<int> seg;
  // [1,n]
  BIT(int N) { seg.resize(N + 1, 0); };
  void add(int i, int x) { seg[i] = seg[i] + x; }
  void init() {
    for (int i = 1; i < seg.size(); i++) {
      seg[i] += seg[i - 1];
      seg[i] %= 1000000007;
    }
  }
  inline int get(int l, int r) { return (seg[r] - seg[l - 1]) % 1000000007; }
};

int main() {
  int N, Q;
  cin >> N >> Q;
  for (int i = 1; i <= N; i++) {
    scanf("%d", &p[i]);
  }

  SegmentTree<long long> LCM(N);
  SegmentTree2<long long> MX(N);
  vector<BIT> bit1(41, BIT(N));

  for (int i = 1; i <= N; i++) {
    if (done[i])
      continue;
    len = 0;
    v.clear();
    dfs(i);
    long long sum = 0;
    for (int j = 0; j < v.size(); j++) {
      sum += v[j];
      sum %= 1000000007;
      MX.add(v[j], len);
      LCM.add(v[j], len);
    }
    for (int j = 0; j < v.size(); j++) {
      bit1[len].add(v[j], sum);
    }
  }
  for (int j = 1; j <= 40; j++) {
    bit1[j].init();
  }
  for (int i = 0; i < Q; i++) {
    long long ans = 0;
    long long l, r;
    cin >> l >> r;
    long long len = LCM.get(l, r);
    long long mx = MX.get(l, r);
    for (int j = 1; j <= mx; j++) {
      if (len % j != 0)
        continue;
      ans += (len / j) % 1000000007 * bit1[j].get(l, r) % 1000000007;
      ans %= 1000000007;
    }
    printf("%d\\n", (int)ans);
  }
}