hdu 5645(树状数组)

题意:
给一个盒子,里面装着 n 个球,每个球有个权值,现要从盒子里拿出两个球,求第一个球的权值大于第二个球的权值的概率。共t组样例, n 个球,每个球的权值分别为ai。其中, 1t300,2n300,1ai300

思路:
首先,很容易想出总的情况的个数为 n(n1) ,那么我们只需找出满足要求的情况个数即可。
暴力解法:二重循环直接枚举出所有 ai>aj 的种类数,最后除以 n(n1) ,完事。复杂度为 O(n2)
有意思的解法:我们的核心任务是求出 ai>aj 的种类数,那么我们可以借助下树状数组这种科技,我们可以在 O(logn) 的时间内在 ai 这个位置插入一个1,表示下这个位置有个数,然后在所有的数都处理完之后在对每个 ai 找一下它前面有多少个数,这个操作也是 O(logn) 的,那么总的复杂度自然为 O(nlogn) 了。

上个代码:

#include <cstdio>
#include <cstring>

const int MAXN = 400;
int a[MAXN], c[MAXN];

inline int lowbit(int x){
        return x & -x;
}

void add(int pos, int p){
        for(int i = pos; i < MAXN; i += lowbit(i)){
                c[i] += p;
        }
        return;
}

int query(int pos){
        int sum = 0;
        while(pos){
                sum += c[pos];
                pos -= lowbit(pos);
        }
        return sum;
}

int main(int argc, char const *argv[]){
        int cas;
        scanf("%d", &cas);
        while(cas--){
                int n;
                scanf("%d", &n);
                memset(c, 0, sizeof(c));
                for(int i = 0; i < n; i++){
                        scanf("%d", a + i);
                        add(a[i], 1);
                }
                int sum = 0;
                for(int i = 0; i < n; i++){
                        sum += query(a[i] - 1);
                }

                printf("%.6f\n", sum * 1.0 / ( (n - 1) * n) );
        }
        return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值