F. Inversion Expectation
题意:
输入
n
(
2
e
5
)
n(2e5)
n(2e5);
输入一个长度为
n
n
n的有不确定数的排列,
p
1
,
p
2
,
…
,
p
n
p_1,p_2,\dots,p_n
p1,p2,…,pn,不确定数为
−
1
-1
−1。
问逆序对的期望个数是多少。
题解:
分三种情况计算贡献就好。
1、两数确定,直接用BIT求二维偏序就好。
2、一数确定,另外一数不确定;按确定数从左到右枚举,它的贡献为
比它大的不确定数的个数
×
\times
×左边-1数+比它小的不确定数个数
×
\times
×右边-1数。
最后出上总的-1数。
3、两数都不确定,直接排列组合枚举就好。
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=2e5+9;
int n,p[N];
const int mod=998244353;
int ans,blk[N];
int f[N];
void add(int x,int y){for(;x<N;x+=(x&-x))f[x]+=y;}
int query(int x){int ans=0;while(x)ans+=f[x],x-=(x&-x);return ans;}
int poww(int a,int b,int c){
int ans=1,base=a;
while(b){
if(b&1)ans=1ll*ans*base%c;
base=1ll*base*base%c;
b>>=1;
}
return ans;
}
int inv(int x){return poww(x,mod-2,mod);}
int main(){
//freopen("tt.in","r",stdin),freopen("tt.out","w",stdout);
cin>>n;
for(int i=1;i<=n;i++)cin>>p[i];
for(int i=1;i<=n;i++)if(p[i]==-1)blk[i]=blk[i-1]+1;else{
ans=(query(N-1)-query(p[i])+ans)%mod;
add(p[i],1);
blk[i]=blk[i-1];
}
for(int i=1;i<=n;i++)if(p[i]!=-1){
int d=(n-p[i])-(query(N-1)-query(p[i]));
int x=(p[i]-1)-query(p[i]-1);
ans+=(1ll*d*blk[i]+1ll*x*(blk[n]-blk[i]))%mod*inv(blk[n])%mod;
ans%=mod;
}
int t3=1ll*blk[n]*(blk[n]-1)/2%mod;
t3=1ll*t3*t3%mod;
t3=1ll*t3*inv(blk[n])%mod*inv(blk[n]-1)%mod;
ans=(ans+t3)%mod;
cout<<ans<<endl;
return 0;
}