Problem p01718 (C++) — buggy submission, verdict: Runtime Error

#include <bits/stdc++.h>
#define FOR(i, k, n) for (int i = (k); i < int(n); ++i)
#define REP(i, n) FOR(i, 0, n)
#define ALL(x) begin(x), end(x)

using ll = long long;
constexpr ll mod = 1000000007;

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

using namespace std;
struct Data {
  ll num;
  ll sum;
  Data() : num(1), sum(0) { ; }
  Data(int64_t n, int64_t s) : num(n), sum(s) { ; }
};
ll inv(ll a, ll p) { return (a == 1 ? 1 : (1 - p * inv(p % a, a)) / a + p); }

inline Data Merge(Data left, Data right) {
  ll l = lcm(left.num, right.num);
  ll g = gcd(left.num, right.num);
  ll llinv = (right.num / g) % mod;
  ll lrinv = (left.num / g) % mod;
  ll s = left.sum * llinv + right.sum * lrinv;
  return Data(l, s % mod);
}

struct SegmentTree {
  int n;
  vector<Data> data;
  SegmentTree(int N) : n(1 << N), data(n * 2) {}
  void update(int pos, Data value) {
    data[pos] = value;
    while (pos < 2 * n - 1) {
      int l = pos, r = pos ^ 1;
      if (l > r)
        swap(l, r);
      pos = pos / 2 + n;
      data[pos] = Merge(data[l], data[r]);
    }
  }
  Data sub(int fr, int to, int node, int la, int ra) {
    if (ra <= fr || to <= la)
      return Data();
    if (fr <= la && ra <= to)
      return data[node];
    Data vl = sub(fr, to, (node - n) * 2 + 0, la, (la + ra) / 2);
    Data vr = sub(fr, to, (node - n) * 2 + 1, (la + ra) / 2, ra);
    return Merge(vl, vr);
  }
  Data query(int fr, int to) { return sub(fr, to, 2 * n - 2, 0, n); }
};

int main() {
  int64_t n, q;
  cin >> n >> q;
  vector<int64_t> p(n);
  REP(i, n) { cin >> p[i]; }
  vector<int64_t> c(n, 43);
  vector<int64_t> sum(n, 0);
  vector<int64_t> x(n, 0);
  iota(ALL(x), 1);
  REP(i, 42) {
    vector<int64_t> y = x;
    REP(j, n) y[j] = p[x[j] - 1];
    swap(x, y);
    REP(j, n) if (c[j] > 41) sum[j] += x[j];
    REP(j, n) if (x[j] == j + 1) c[j] = min(c[j], (int64_t)i + 1);
  }
  SegmentTree st(17);
  REP(i, n) st.update(i, Data(c[i], sum[i] % mod));
  REP(i, q) {
    int64_t l, r;
    cin >> l >> r;
    --l;
    --r;
    auto res = st.query(l, r + 1);
    cout << res.sum << endl;
  }
  return 0;
}

Error: 0

Fixed submission:

#include <bits/stdc++.h>
#define FOR(i, k, n) for (int i = (k); i < int(n); ++i)
#define REP(i, n) FOR(i, 0, n)
#define ALL(x) begin(x), end(x)

using ll = long long;
constexpr ll mod = 1000000007;

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

using namespace std;
struct Data {
  ll num;
  ll sum;
  Data() : num(1), sum(0) { ; }
  Data(int n, int s) : num(n), sum(s) { ; }
};
ll inv(ll a, ll p) { return (a == 1 ? 1 : (1 - p * inv(p % a, a)) / a + p); }

inline Data Merge(Data left, Data right) {
  ll l = lcm(left.num, right.num);
  ll llinv = (l * inv(left.num, mod)) % mod;
  ll lrinv = (l * inv(right.num, mod)) % mod;
  ll s = left.sum * llinv + right.sum * lrinv;
  return Data(l, s % mod);
}

struct SegmentTree {
  int n;
  vector<Data> data;
  SegmentTree(int N) : n(1 << N), data(n * 2) {}
  void update(int pos, Data value) {
    data[pos] = value;
    while (pos < 2 * n - 1) {
      int l = pos, r = pos ^ 1;
      if (l > r)
        swap(l, r);
      pos = pos / 2 + n;
      data[pos] = Merge(data[l], data[r]);
    }
  }
  Data sub(int fr, int to, int node, int la, int ra) {
    if (ra <= fr || to <= la)
      return Data();
    if (fr <= la && ra <= to)
      return data[node];
    Data vl = sub(fr, to, (node - n) * 2 + 0, la, (la + ra) / 2);
    Data vr = sub(fr, to, (node - n) * 2 + 1, (la + ra) / 2, ra);
    return Merge(vl, vr);
  }
  Data query(int fr, int to) { return sub(fr, to, 2 * n - 2, 0, n); }
};

int main() {
  int n, q;
  cin >> n >> q;
  vector<int> p(n);
  REP(i, n) { cin >> p[i]; }
  vector<int> c(n, 43);
  vector<int64_t> sum(n, 0);
  vector<int> x(n, 0);
  iota(ALL(x), 1);
  REP(i, 42) {
    vector<int> y = x;
    REP(j, n) y[j] = p[x[j] - 1];
    swap(x, y);
    REP(j, n) if (c[j] > 41) sum[j] += x[j];
    REP(j, n) if (x[j] == j + 1) c[j] = min(c[j], i + 1);
  }
  SegmentTree st(18);
  REP(i, n) st.update(i, Data(c[i], sum[i] % mod));
  REP(i, q) {
    int l, r;
    cin >> l >> r;
    --l;
    --r;
    auto res = st.query(l, r + 1);
    cout << res.sum << endl;
  }
  return 0;
}