Codeforces 1096F(dp + 樹狀數組)
阿新 • • 發佈:2019-02-05
逆序對 貢獻 lap 數量 comm type int rst else
題目鏈接
題意:
對於長度為$n$的排列,在已知一些位的前提下求逆序對的期望
思路:
將答案分為$3$部分
$1.$$-1$與$-1$之間對答案的貢獻。由於逆序對考慮的是數字之間的大小關系,故假設$-1$的數量為$cnt$,可以等效成求長度為$cnt$的排列的逆序對期望。設$dp[i]$為長度為$i$的全排列的逆序對期望,有$dp[i]=dp[i-1]+$$\frac{i-1}{2}$,可以理解成在原$dp[i-1]$的基礎上,數值$i$對每個長度為$i-1$的排列產生$\sum_{t=1}^{i-1}t$個逆序對,共有$(i-1)!$個排列,所以期望為$\frac{(i-1)!*i*(i-1)}{(2*i!)}$$=\frac{i-1}{2}$,移項後使用累加法可以求出通項為$dp[i]=$$\frac{i*(i-1)}{4}$。
$2.$非$-1$之間對答案的貢獻。可以將出現概率看作$1$,所以貢獻就是逆序對數量,用樹狀數組求。
$3.$$-1$與非$-1$之間的貢獻。設共有$cnt$個$-1$,考慮每個$a[i]$$\neq$$-1$,設這個$a[i]$它前邊$-1$的數量為$nop$,它大的未填的數的數量為$high[a[i]]$,那麽$a[i]$對這部分答案的貢獻為$\frac{nop*high[a[i]]*(cnt-1)!}{cnt!}$$=$$\frac{nop*high[a[i]]}{cnt}$。比$a[i]$小的數與$a[i]$後邊的$-1$構成類似的關系。
代碼:
//#pragma comment(linker, "/STACK:1024000000,1024000000") #include <map> #include <set> #include <cmath> #include <queue> #include <stack> #include <cstdio> #include <vector> #include <cassert> #include <cstring> #include <iostream> #include <algorithm> #define IOS ios::sync_with_stdio(0),cin.tie(0); #define DBG(x) cerr << #x << " = " << x << endl; #define PII pair<int,int> #define FI first #define SE second using namespace std; typedef long long LL; typedef long double LD; typedef unsigned long long ULL; const int inf = 0x3f3f3f3f; const int mod = 998244353; const double eps = 1e-8; const double pi = acos(-1.0); void file(){ freopen("in.txt", "r", stdin); freopen("out.txt", "w", stdout); } namespace BakuretsuMahou{ const int N = 2e5 + 5; const int inv2 = (mod + 1) / 2; int n, a[N], vis[N]; int high[N], low[N]; int pre[N], cnt; LL ans, fac[N]; LL add(LL a, LL b){ return (a+b)%mod; } LL mul(LL a, LL b){ return (a*b)%mod; } struct BIT{ int c[N]; int lowbit(int x){ return (x)&(-x); } void update(int x, int y){ while(x <= n){ c[x] += y; x += lowbit(x); } } LL query(int x){ LL res = 0; while(x >= 1){ res += c[x]; x -= lowbit(x); } return res; } }tree; LL qpow(LL a, LL b, LL p){ LL res = 1; while(b){ if(b&1)res = mul(res, a); a = mul(a, a); b >>= 1; } return res; } LL Fermat(LL a, LL p){ return qpow(a, p - 2, p); } LL dp(LL x){ return mul(mul(x, x - 1), Fermat(4, mod)); } void init(){ fac[0] = 1; for(int i = 1; i < N; i++){ fac[i] = mul(fac[i - 1], i); } } void Explosion(){ init(); scanf("%d", &n); for(int i = 1; i <= n; i++){ scanf("%d", &a[i]); if(a[i] != -1){ vis[a[i]] = 1; ans = add(ans, i - 1 - cnt - tree.query(a[i])); tree.update(a[i], 1); }else cnt++, pre[i]++; pre[i] += pre[i - 1]; } ans = add(ans, dp(cnt)); LL inv = Fermat(cnt, mod); for(int i = 2; i <= n; i++)low[i] = low[i - 1] + (vis[i - 1] ^ 1); for(int i = n - 1; i >= 1; i--)high[i] = high[i + 1] + (vis[i + 1] ^ 1); for(int i = 1; i <= n; i++){ if(a[i] != -1){ LL nop = pre[i], nos = pre[n] - pre[i]; ans = add(ans, mul(mul(nos, low[a[i]]), inv)); ans = add(ans, mul(mul(nop, high[a[i]]), inv)); } } printf("%I64d\n", ans); } } int main(){ //IOS //file(); BakuretsuMahou::Explosion(); return 0; }
Codeforces 1096F(dp + 樹狀數組)