zoukankan      html  css  js  c++  java
  • 【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;
    }
    
  • 相关阅读:
    限制页面只能在框架页中
    Excel导入的HDR=YES; IMEX=1详解
    ASP复制文件
    C#获取当前日期时间
    SQL语句添加删除修改字段
    C#代码调用页面javascript函数
    JavaScript 层
    vue-router实现SPA购物APP基本功能
    iOS自定义从底部弹上来的View
    RabbitMQ消息队列生产者和消费者
  • 原文地址:https://www.cnblogs.com/MashiroSky/p/6246624.html
Copyright © 2011-2022 走看看