1. 程式人生 > >CF1096F.Inversion Expectation[樹狀陣列+概率期望] Educational Codeforces Round 57

CF1096F.Inversion Expectation[樹狀陣列+概率期望] Educational Codeforces Round 57

給一個排列(有些是-1,代表等概率是沒出現過數字中的任意一個),求期望逆序對個數

分成三部分(x表示已知)

  • -1和-1之間的
  • -1和x之間的
  • x和x之間的

具體柿子在下面

```cpp
// -1 -1 cnt * (cnt - 1) / 2 / 2
// -1 x cnt(-1) * cnt(-1) / cnt(-1)
// x -1 cnt(-1) * cnt(-1) / cnt(-1)
// x x

int a[MAXN], n, gt[MAXN], ls[MAXN], cnt[MAXN]; //cnt[i] [1..i]-1的個數 gt[i] 比 i 大的-1個數 | ls[i] 比 i 小的-1個數
bool vis[MAXN];

struct BIT {
int t[MAXN];
inline void add(int k, int v) {
while (k <= n) t[k] += v, k += k & -k;
}
inline int query(int k) {
int ret = 0;
while (k) ret += t[k], k -= k & -k;
return ret;
}
} bit;
// a[i] -> gt[1,a[i]-1]
// a[i] -> ls[a[i]+1,n]

int main() {
int ans = 0, tmp = 0;
in, n;
lop1(i, n) {
in, a[i];
if (~a[i]) vis[a[i]] = 1, bit.add(a[i], 1), ans += ++tmp - bit.query(a[i]), Mod(ans, mod);
else cnt[i] = 1;

}
// out, ans, '\n';
lop1(i, n) {
cnt[i] += cnt[i-1];
if (!vis[i]) ++gt[1], --gt[i], ++ls[i + 1];//, --ls[n + 1];
}
ans += cnt[n] * 1ll * (cnt[n] - 1) % mod * Pow(4, mod-2, mod) % mod;
Mod(ans, mod);
lop1(i, n) gt[i] += gt[i-1], ls[i] += ls[i-1];
int Inv = Pow(cnt[n], mod - 2, mod);
lop1(i, n)
if (~a[i]) {
int x = ls[a[i]] * 1ll * (cnt[n] - cnt[i - 1]) % mod + gt[a[i]] * 1ll * cnt[i - 1] % mod;
Mod(x, mod);
ans += x * 1ll * Inv % mod;
Mod(ans, mod);
}
out, ans;
return 0;
}
```C