这个题感觉比较简单?可是场上只过了
7
7
7个人。
如果要计数有多少个排列是经典问题,按
A
i
A_i
Ai排序后,答案就是
∏
i
=
1
n
(
A
i
−
i
+
1
)
\prod_{i=1}^{n}(A_i-i+1)
∏i=1n(Ai−i+1)。
现在要求逆序对的总数,显然考虑枚举点对计数。假设我们算的是
(
i
,
j
)
(
i
<
j
)
(i,j)(i<j)
(i,j)(i<j)的贡献,那么当
A
i
≤
A
j
A_i \leq A_j
Ai≤Aj的时候,排序后
i
i
i会在
j
j
j前面,我们可以在考虑
i
i
i的时候让它把
j
j
j也一起选了,这样会把中间一段的
A
i
A_i
Ai减
1
1
1,稍微计算一下就行了。当
A
i
>
A
j
A_i>A_j
Ai>Aj的时候
j
j
j会跑到
i
i
i的前面,不好统计,考虑统计反面的情况,即
p
i
<
p
j
p_i<p_j
pi<pj的数目,同样可以类似的做。
实现的时候从后往前扫描,可以用个线段树维护,复杂度
O
(
n
log
n
)
\mathcal O(n\log n)
O(nlogn)。
#include <bits/stdc++.h>
#define lowbit(x) (x&-x)
#define FR first
#define SE second
#define MOD 1000000007
using namespace std;
typedef long long ll;
typedef pair<int,int> pr;
int sumv[200005];
void add(int x) {
for(;x;x-=lowbit(x)) sumv[x]++;
}
int sum(int x,int n) {
int s=0;
for(;x<=n;x+=lowbit(x)) s+=sumv[x];
return s;
}
namespace SGT {
ll mulv[800000],sumv[800000];
inline void pushup(int o) {
sumv[o]=(sumv[o*2]+sumv[o*2+1])%MOD;
}
inline void pushdown(int o) {
if (mulv[o]!=1) {
mulv[o*2]=mulv[o*2]*mulv[o]%MOD;
mulv[o*2+1]=mulv[o*2+1]*mulv[o]%MOD;
sumv[o*2]=sumv[o*2]*mulv[o]%MOD;
sumv[o*2+1]=sumv[o*2+1]*mulv[o]%MOD;
mulv[o]=1;
}
}
void build(int l,int r,int o) {
mulv[o]=1;
if (l==r) return;
else {
int m=((l+r)>>1);
build(l,m,o*2);
build(m+1,r,o*2+1);
}
}
void update1(int l,int r,int o,int p,int q) {
if (l==r) sumv[o]=q;
else {
pushdown(o);
int m=((l+r)>>1);
if (m>=p) update1(l,m,o*2,p,q);
else update1(m+1,r,o*2+1,p,q);
pushup(o);
}
}
void update2(int p) {
mulv[1]=mulv[1]*p%MOD;
}
int query(int l,int r,int o,int lx,int rx) {
if (l>=lx&&r<=rx) return sumv[o];
else {
pushdown(o);
int m=((l+r)>>1);
if (m>=rx) return query(l,m,o*2,lx,rx);
if (m<lx) return query(m+1,r,o*2+1,lx,rx);
return (query(l,m,o*2,lx,rx)+query(m+1,r,o*2+1,lx,rx))%MOD;
}
}
}
int num[200005],pre[200005];
pr val[200005];
inline ll C(ll n) {
return (n*(n-1)>>1)%MOD;
}
int main() {
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++) {
scanf("%d",&num[i]);
val[i]=pr(num[i],i);
}
sort(val+1,val+n+1);
pre[0]=1;
for(int i=1;i<=n;i++) {
if (val[i].FR<i) {
puts("0");
return 0;
}
pre[i]=(ll)pre[i-1]*(val[i].FR-i+1)%MOD;
}
int s=0;
for(int i=1;i<=n;i++) {
add(num[i]);
s=(s+sum(num[i]+1,n))%MOD;
}
int ans=(ll)s*pre[n]%MOD;
SGT::build(1,n,1);
s=1;
for(int i=n;i>0;i--) {
int x=val[i].SE,v=val[i].FR;
ans=(ans+(ll)pre[i-1]*SGT::query(1,n,1,x,n)%MOD*C(v-i+1))%MOD;
ans=(ans-(ll)pre[i-1]*SGT::query(1,n,1,1,x)%MOD*C(v-i+1)%MOD+MOD)%MOD;
SGT::update2(v-i);
SGT::update1(1,n,1,x,s);
s=(ll)s*(v-i+1)%MOD;
}
printf("%d\n",ans);
return 0;
}