Problem p03367 (C++)

Buggy submission (status: Runtime Error):
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 100005, M = 1e9 + 7, Inv = M / 2 + 1;
int a[N], cnt[N], f[N], d[N], pre[N], nxt[N], n;
struct Tree {
  int l, r, num1, num2, num3;
} T[N * 4];
int ksm(int x, int y) {
  int ans = 1;
  for (; y; y >>= 1, x = x * x % M)
    if (y & 1)
      (ans *= x) %= M;
  return ans;
}
void build(int x, int l, int r) {
  T[x].l = l;
  T[x].r = r;
  if (l == r)
    return;
  int mid = (l + r) / 2;
  build(x * 2, l, mid);
  build(x * 2 + 1, mid + 1, r);
}
void insert(int x, int y) {
  if (T[x].l == T[x].r) {
    T[x].num3++;
    (T[x].num2 += ksm(f[T[x].l], M - 2)) %= M;
    (T[x].num1 += f[T[x].l]) %= M;
    return;
  }
  int mid = (T[x].l + T[x].r) / 2;
  if (y <= mid)
    insert(x * 2, y);
  else
    insert(x * 2 + 1, y);
  T[x].num1 = (T[x * 2].num1 + T[x * 2 + 1].num1) % M;
  T[x].num2 = (T[x * 2].num2 + T[x * 2 + 1].num2) % M;
  T[x].num3 = (T[x * 2].num3 + T[x * 2 + 1].num3) % M;
}
int find1(int x, int l, int r) {
  if (T[x].l > r || l > T[x].r)
    return 0;
  if (T[x].l >= l && T[x].r <= r)
    return T[x].num1;
  return (find1(x * 2, l, r) + find1(x * 2 + 1, l, r)) % M;
}
int find2(int x, int l, int r) {
  if (T[x].l > r || l > T[x].r)
    return 0;
  if (T[x].l >= l && T[x].r <= r)
    return T[x].num2;
  return (find2(x * 2, l, r) + find2(x * 2 + 1, l, r)) % M;
}
int find3(int x, int l, int r) {
  if (T[x].l > r || l > T[x].r)
    return 0;
  if (T[x].l >= l && T[x].r <= r)
    return T[x].num3;
  return (find3(x * 2, l, r) + find3(x * 2 + 1, l, r)) % M;
}
signed main() {
  scanf("%lld", &n);
  for (int i = 1; i <= n; i++)
    scanf("%lld", &a[i]), cnt[a[i]]++;
  for (int i = n; i; i--)
    cnt[i] += cnt[i + 1];
  for (int i = 1; i <= n; i++)
    cnt[i] -= n - i;
  int num = 1;
  for (int i = 1; i <= n; i++)
    (num *= cnt[i]) %= M;
  if (!num) {
    puts("0");
    return 0;
  }
  f[0] = 1;
  for (int i = 1; i <= n; i++) {
    d[i] = (cnt[i] - 1) * ksm(cnt[i], M - 2) % M;
    f[i] = f[i - 1] * (d[i] == 0 ? 1 : d[i]) % M;
  }
  pre[1] = 1;
  nxt[n] = n + 1;
  for (int i = 2; i <= n; i++) {
    if (!d[i])
      pre[i] = i;
    else
      pre[i] = pre[i - 1];
  }
  for (int i = n - 1; i; i--) {
    if (!d[i + 1])
      nxt[i] = i + 1;
    else
      nxt[i] = nxt[i + 1];
  }
  int ans = 0;
  build(1, 1, n);
  for (int i = n; i; i--) {
    (ans += num * find1(1, a[i] + 1, nxt[a[i]] - 1) % M * ksm(f[a[i]], M - 2) %
            M * Inv) %= M;
    (ans += num * find3(1, 1, a[i]) -
            num * find2(1, pre[a[i]], a[i]) % M * f[a[i]] % M * Inv % M + M) %=
        M;
    insert(1, a[i]);
  }
  printf("%lld\n", ans);
  return 0;
}

Fixed submission:
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 200005, M = 1e9 + 7, Inv = M / 2 + 1;
int a[N], cnt[N], f[N], d[N], pre[N], nxt[N], n;
struct Tree {
  int l, r, num1, num2, num3;
} T[N * 4];
int ksm(int x, int y) {
  int ans = 1;
  for (; y; y >>= 1, x = x * x % M)
    if (y & 1)
      (ans *= x) %= M;
  return ans;
}
void build(int x, int l, int r) {
  T[x].l = l;
  T[x].r = r;
  if (l == r)
    return;
  int mid = (l + r) / 2;
  build(x * 2, l, mid);
  build(x * 2 + 1, mid + 1, r);
}
void insert(int x, int y) {
  if (T[x].l == T[x].r) {
    T[x].num3++;
    (T[x].num2 += ksm(f[T[x].l], M - 2)) %= M;
    (T[x].num1 += f[T[x].l]) %= M;
    return;
  }
  int mid = (T[x].l + T[x].r) / 2;
  if (y <= mid)
    insert(x * 2, y);
  else
    insert(x * 2 + 1, y);
  T[x].num1 = (T[x * 2].num1 + T[x * 2 + 1].num1) % M;
  T[x].num2 = (T[x * 2].num2 + T[x * 2 + 1].num2) % M;
  T[x].num3 = (T[x * 2].num3 + T[x * 2 + 1].num3) % M;
}
int find1(int x, int l, int r) {
  if (T[x].l > r || l > T[x].r)
    return 0;
  if (T[x].l >= l && T[x].r <= r)
    return T[x].num1;
  return (find1(x * 2, l, r) + find1(x * 2 + 1, l, r)) % M;
}
int find2(int x, int l, int r) {
  if (T[x].l > r || l > T[x].r)
    return 0;
  if (T[x].l >= l && T[x].r <= r)
    return T[x].num2;
  return (find2(x * 2, l, r) + find2(x * 2 + 1, l, r)) % M;
}
int find3(int x, int l, int r) {
  if (T[x].l > r || l > T[x].r)
    return 0;
  if (T[x].l >= l && T[x].r <= r)
    return T[x].num3;
  return (find3(x * 2, l, r) + find3(x * 2 + 1, l, r)) % M;
}
signed main() {
  scanf("%lld", &n);
  for (int i = 1; i <= n; i++)
    scanf("%lld", &a[i]), cnt[a[i]]++;
  for (int i = n; i; i--)
    cnt[i] += cnt[i + 1];
  for (int i = 1; i <= n; i++)
    cnt[i] -= n - i;
  int num = 1;
  for (int i = 1; i <= n; i++)
    (num *= cnt[i]) %= M;
  if (!num) {
    puts("0");
    return 0;
  }
  f[0] = 1;
  for (int i = 1; i <= n; i++) {
    d[i] = (cnt[i] - 1) * ksm(cnt[i], M - 2) % M;
    f[i] = f[i - 1] * (d[i] == 0 ? 1 : d[i]) % M;
  }
  pre[1] = 1;
  nxt[n] = n + 1;
  for (int i = 2; i <= n; i++) {
    if (!d[i])
      pre[i] = i;
    else
      pre[i] = pre[i - 1];
  }
  for (int i = n - 1; i; i--) {
    if (!d[i + 1])
      nxt[i] = i + 1;
    else
      nxt[i] = nxt[i + 1];
  }
  int ans = 0;
  build(1, 1, n);
  for (int i = n; i; i--) {
    (ans += num * find1(1, a[i] + 1, nxt[a[i]] - 1) % M * ksm(f[a[i]], M - 2) %
            M * Inv) %= M;
    (ans += num * find3(1, 1, a[i]) -
            num * find2(1, pre[a[i]], a[i]) % M * f[a[i]] % M * Inv % M + M) %=
        M;
    insert(1, a[i]);
  }
  printf("%lld\n", ans);
  return 0;
}