• CF749E Inversions After Shuffle


    Link
    我们可以把贡献拆成两部分计算。
    对于一对(a_i,a_j(i<j)),如果我们重排的区间([l,r])满足([i,j]subseteq[l,r]),那么不论(a_i,a_j)的关系如何,它们都有(frac12)的概率产生(1)的贡献。
    这里的总的贡献是(frac{sumlimits_{i=1}^nsumlimits_{j=i+1}^ni(n-j+1)}{n(n+1)}=frac{sumlimits_{i=1}^ni(n-i)(n-i+1)}{n(n+1)})
    其实可以推出(O(1))的式子,不过没有必要了。
    对于一对(a_i,a_j(i<jwedge a_i>a_j)),如果我们重排的区间([l,r])满足([i,j] otsubseteq[l,r]),那么它们就会产生(1)的贡献。
    这里总的贡献是(frac{sumlimits_{i=1}^nsumlimits_{j=i+1}^n[a_i>a_j][n(n+1)-i(n-j+1)]}{n(n+1)}=sumlimits_{i=1}^nsumlimits_{j=i+1}^n[a_i>a_j]-frac{sumlimits_{i=1}^nsumlimits_{j=i+1}^n[a_i>a_j]i(n-j+1)}{n(n+1)})
    树状数组维护一下就好了。

    #include<cstdio>
    #include<cctype>
    const int N=100007;
    int read(){int x=0,c=getchar();while(!isdigit(c))c=getchar();while(isdigit(c))x=x*10+c-48,c=getchar();return x;}
    using db=double;
    using ll=long long;
    int n;
    struct bit
    {
        ll t[N];
        void add(int p,int v){for(;p;p^=p&-p)t[p]+=v;}
        ll ask(int p){ll s=0;for(;p<=n;p+=p&-p)s+=t[p];return s;}
    }t1,t2;
    int main()
    {
        n=read();db ans=0,Ans=0;
        for(int i=1,a;i<=n;++i) a=read(),Ans+=t1.ask(a+1),ans+=(db)(n-i+1)*i*(n-i)/4.0-(db)t2.ask(a+1)*(n-i+1),t1.add(a,1),t2.add(a,i);
        printf("%.10lf",Ans+ans/(1ll*n*(n+1)>>1));
    }
    
  • 相关阅读:
    浅谈动态开点线段树
    详解二叉查找树(BST)
    数组的随机打乱
    浅谈迭代加深搜索
    浅谈传递闭包问题
    详解权值线段树
    算法竞赛中桶的概念与应用
    NKOJ 1353 图形面积
    并查集 & 最小生成树详细讲解
    【线段树基础】NKOJ 1321 数列操作
  • 原文地址:https://www.cnblogs.com/cjoierShiina-Mashiro/p/12193934.html
Copyright © 2020-2023  润新知