日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【codeforces 749E】 Inversions After Shuffle

發布時間:2023/12/10 编程问答 53 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【codeforces 749E】 Inversions After Shuffle 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

http://codeforces.com/problemset/problem/749/E?(題目鏈接)

題意

  給出一個1~n的排列,從中等概率的選取一個連續段,設其長度為l。對連續段重新進行等概率的全排列,求排列后整個原序列的逆序對的期望個數。

Solution

  考慮對于每一對數${(a_i,a_j),i<j}$算貢獻。


?  1.連續段包含${a_i,a_j}$

  不妨設${a_i<a_j}$,則只有當排列后${a_j}$再${a_i}$前面才會對答案有貢獻(${a_i>a_j}$的情況同理),連續段長度為${l}$。

  于是滿足${a_i}$在${a_j}$前面的排列數為${P_l^{l-2}}$,概率:${\frac{P_l^{l-2}}{P_l^l}=\frac{1}{2}}$。

  滿足包含${a_i}$和${a_j}$的連續段有${i*(n-j+1)}$個,其概率為:${\frac{2*i*(n-j+1)}{n*(n+1)}}$。

  所以其期望等于兩個概率相乘:

  $${q_{i,j}=\frac{i*(n-j+1)}{n*(n+1)}}$$

  這是${O(n^2)}$的,考慮優化。總期望:

  $${Q=\sum_{i=1}^n ?\sum_{j=i+1}^n ?q_{i,j}}$$

  $${Q=\sum_{i=1}^n ?\sum_{j=i+1}^n ?\frac{i*(n-j+1)}{n*(n+1)}}$$

  發現${(n-j+1)}$是連續的,于是就變成了:

  $${Q=\sum_{i=1}^n ?\frac {i*(n-i)*(n-i+1)} {2*n*(n+1)}}$$

  這樣復雜度就是${O(n)}$的了。


  2.連續段不同時包含${a_i,a_j}$

  如果${a_i<a_j}$,那么因為不被連續段同時包含,它們不會有機會改變相對位置,所以不會對答案做出貢獻。考慮${a_i>a_j}$的情況。

  那么連續段可能取到的區間有:${[1,j-1],[i+1,n]}$。考慮到區間${[i+1,j-1]}$被算了2次,容斥一下,所以區間的概率:

  $${P_{i,j}=\frac ?{(j-1)*j+(n-i)*(n-i+1)-(j-i-1)*(j-i)} ?{n*(n+1)}}$$

  $${P_{i,j}=\frac ?{(n^2+n)-(2*i+2*n*i)+2*i*j} ?{n*(n+1)}}$$

  這個${P_{i,j}}$怎么快速求解呢,考慮逆序對這個東西。

  $${Q=\sum_{i=1}^n ?\sum_{j=i+1}^n ?\frac ?{(n^2+n)-(2*i+2*n*i)+2*i*j} ?{n*(n+1)}}$$

  設滿足${a_j<a_i,j>i}$的${a_j}$的個數為${x}$,顯然${x}$我們可以通過樹狀數組用求逆序對的方法${O(nlogn)}$的求出來,則:

  $${Q=\sum_{i=1}^n ?\frac ?{x*((n^2+n)-(2*i+2*n*i)) ?+ ?\sum_{j=i+1}^n 2*i*j} ?{n*(n+1)}}$$

  那么現在${\sum_{j=i+1}^n 2*i*j}$怎么求呢。把${2*i}$提出去,那么就成了${2*i*\sum_{j=i+1}^n j}$我們用${y}$記錄滿足${a_j<a_i,j>i}$的${a_j}$的位置的和,也就是${\sum_{j=i+1}^n j}$,那么顯然這個東西我們也是可以通過樹狀數組用求逆序對的方法${O(nlogn)}$的算出來的。則:

  $${Q=\sum_{i=1}^n ?\frac ?{x*((n^2+n)-(2*i+2*n*i)) ?+ ?2*i*y} ?{n*(n+1)}}$$

  于是問題就${O(nlogn)}$的解決了。

細節

  mdzz不曉得哪里爆掉了還是精度問題,調了2天,最后莫名AC。。。

代碼

// codeforces 749E #include<algorithm> #include<iostream> #include<cstdlib> #include<cstring> #include<cstdio> #include<cmath> #define LL long long #define inf 1<<30 #define Pi acos(-1.0) #define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout); using namespace std;const int maxn=100010; LL c[maxn],s[maxn],n; int a[maxn]; long double ans;int lowbit(int x) {return x&-x; } void add(LL *c,int x,LL val) {for (int i=x;i<=n;i+=lowbit(i)) c[i]+=val; } LL query(LL *c,int x) {LL res=0;for (int i=x;i;i-=lowbit(i)) res+=c[i];return res; }void solve1() { //區間包含long double Q=0;for (LL i=1;i<=n;i++)Q+=(long double)(i*(n-i)*(n-i+1))/2/n/(n+1);ans+=Q; } void solve2() { //區間不包含long double Q=0;for (int i=n;i>=1;i--) {LL x=query(c,a[i]-1);Q-=(long double)(x*((2*i+2*n*i)-(n*n+n)))/n/(n+1);Q+=(long double)(2*i)/n/(n+1)*query(s,a[i]-1);add(c,a[i],1);add(s,a[i],i);}ans+=Q; } int main() {scanf("%lld",&n);for (int i=1;i<=n;i++) scanf("%d",&a[i]);solve1();solve2();printf("%.20Lf",ans);return 0; }

貼一個暴力,供參考:

// codeforces 749E #include<algorithm> #include<iostream> #include<cstdlib> #include<cstring> #include<cstdio> #include<cmath> #define LL long long #define inf 1<<30 #define Pi acos(-1.0) #define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout); using namespace std;const int maxn=100010; LL c[maxn],s[maxn],n; int a[maxn]; long double ans;int main() {freopen("aaa.in","r",stdin);freopen("ccc.out","w",stdout);scanf("%lld",&n);for (int i=1;i<=n;i++) scanf("%d",&a[i]);for (LL i=1;i<=n;i++)ans+=(long double)(i*(n-i)*(n-i+1))/(2*n*(n+1));long double res=0;for (LL i=n;i>=1;i--) {for (LL j=i+1;j<=n;j++)if (a[i]>a[j]) res+=(long double)((j-1)*j+(n-i)*(n-i+1)-(j-i-1)*(j-i))/(n*(n+1));}ans+=res;printf("%.20Lf",ans);return 0; }

?

轉載于:https://www.cnblogs.com/MashiroSky/p/6246624.html

總結

以上是生活随笔為你收集整理的【codeforces 749E】 Inversions After Shuffle的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。