AT_agc023_e [AGC023E] Inversions 题解
设 $c_i=\sum\limits_{j=1}^n[a_j\ge i]-n+i$ 表示 $i$ 可选的位置数,
则符合要求的排列共有 $s=\prod\limits_{i=1}^nc_i$ 种,若 $\exists c_i=0$ 显然答案为 $0$。
考虑每对位置 $i,j|i<j$ 在多少排列中是逆序对。先考虑 $a_i\le a_j$ 的情况。
此时 $p_j<p_i\le a_i$,于是令 $a_j\gets a_i$,发现此时 $i,j$ 是逆序对与顺序对的方案数相等,且 $\forall k\in(a_i,a_j],c_k$ 减少 $1$,
所以此时 $i,j$ 在 $\dfrac S2\prod\limits_{k=a_i+1}^{a_j}\dfrac{c_k-1}{c_k}$ 个排列中是逆序对。
考虑预处理 $d_i=\prod\limits_{j=1}^i\dfrac{c_j-1}{c_j}$,则 $\dfrac S2\prod\limits_{k=a_i+1}^{a_j}\dfrac{c_k-1}{c_k}=\dfrac {Sd_{a_j}}{2d_{a_i}}$ 吗?
实际上并不是,考虑 $\dfrac{c_k-1}{c_k}\ne 0$,而 $d_{a_i},d_{a_j}$ 中有 $0$ 的情况。
改变 $d_i$ 的定义为 $d_i=\prod\limits_{j=1,c_j\ne 1}^i\dfrac{c_j-1}{c_j}$,设 $l_i$ 表示 $i$ 前第一个 $c_i=1$ 的位置,
考虑枚举 $j$,则 $j$ 的贡献为 $\dfrac S2\sum\limits_{i=l_{a_j}}^{a_j}\prod\limits_{k=i+1}^{a_j}\dfrac{c_k-1}{c_k}=\dfrac S2\sum\limits_{i=l_{a_j}}^{a_j}\dfrac{d_{a_j}}{d_i}$,此时保证了 $i\ge l_{a_j}$,所以式子成立。
$a$ 值为 $i$ 的位置要求在 $j$ 之前,所以树状数组维护。
$a_i>a_j$ 倒着做一遍。
#include <cstdio>
#include <cstring>
#define M 1000000007
#define int long long
int n, s, q, a[200050], c[200050], d[200050], l[200050];
int P(int x, int y)
{
int q = 1;
for (; y; y >>= 1, x = x * x % M)
if (y & 1)
q = q * x % M;
return q;
}
struct T
{
int c[200050];
void C(int x, int k)
{
for (; x <= n; x += x & -x)
c[x] = (c[x] + k) % M;
}
int Q(int x, int y)
{
int q = 0;
for (x -= !!x; y > x; y &= y - 1)
q = (q + c[y]) % M;
for (; x > y; x &= x - 1)
q = (q + M - c[x]) % M;
return q;
}
} C, D;
signed main()
{
scanf("%lld", &n);
for (int i = 1; i <= n; ++i)
scanf("%lld", a + i), ++c[a[i]];
for (int i = n; i; --i)
c[i] += c[i + 1];
for (int i = 1; i <= n; ++i)
if (!(c[i] -= n - i))
return !puts("0");
d[0] = s = 1;
for (int i = 1; i <= n; ++i)
{
s = s * c[i] % M;
d[i] = d[i - 1] * P(c[i], M - 2) % M;
if (c[i] == 1)
l[i] = i;
else
d[i] = d[i] * (c[i] - 1) % M, l[i] = l[i - 1];
}
for (int i = 1; i <= n; ++i)
q = (q + s * P(2, M - 2) % M * d[a[i]] % M * C.Q(l[a[i]], a[i])) % M, C.C(a[i], P(d[a[i]], M - 2));
memset(C.c, 0, sizeof C.c);
for (int i = n; i >= 1; --i)
q = (q + s * D.Q(1, a[i] - 1) % M + M - s * P(2, M - 2) % M * d[a[i]] % M * C.Q(l[a[i]], a[i] - 1) % M) % M, C.C(a[i], P(d[a[i]], M - 2)), D.C(a[i], 1);
printf("%lld", q);
return 0;
}