【hdu5419】Victor and Toys

  • 求求求
  • 搞搞搞
  • 搞法如下:考虑每个数 w[i] 对答案的贡献,呃。。。首先答案一定是
    [...](m3)
    的形式,只需要搞分子就好了。然后考虑每个数 w[i] 对分子的贡献,假设一个点被 k 个区间所覆盖,那么它的贡献就是
    w[i](k3)
    当然,当 k2 时认为它为 0 就可以统一处理。于是只需要对每个点算出被多少区间覆盖即可。窝用了两个BIT统计,对给定的区间 (u,v) ,窝们把它看成左右括号的形式,当所有括号都在数轴上标记出来以后,窝们怎么统计嘞?可以发现,一个点被覆盖的次数就是该点左边所有左括号的数量减去右括号的数量!另外需要注意,如果一个括号的左右部分都落在这个点上的处理,考虑到这种情况,窝们将上述数量修正为:区间 [1,x] 的左括号数量 区间[1,x1]的右括号数量。直接统计即可得到答案。值得注意的是,只考虑分子部分,极限情况是 50000 5 ,且含50000个区间,均为 [1,50000] ,那么分子为
    550000(500003)<500004=6251016<2631
    是不需要担心会超出 long long 的表示范围的。
/* **********************************************

    File Name: 5419.cpp

    Auther: zhengdongjian@tju.edu.cn

    Created Time: 2015/8/23 星期日 下午 1:35:01

*********************************************** */
#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef pair<int, int> P;
#ifdef ONLINE_JUDGE
#define lld I64d
#endif

typedef long long ll;
const int MAX = 50007;

int a[MAX];
int sum[2][MAX]; //BIT. sum[0] goes up, sum[1] goes down.

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

int query(int id, int x) {
    int s = 0;
    while (x > 0) {
        s += sum[id][x];
        x -= lb(x);
    }
    return s;
}

void modify(int id, int x, int ad) {
    while (x < MAX) {
        sum[id][x] += ad;
        x += lb(x);
    }
} 
//return C(x,3)
inline ll gao1gao(ll x) {
    return x * (x - 1) * (x - 2) / 6;
}

inline void read(int& x) {
    char c;
    while ((c = getchar()) < '0' || c > '9');
    x = c - '0';
    while ((c = getchar()) >= '0' && c <= '9') {
        x = (x << 1) + (x << 3) + c - '0';
    }
}

int main() {
    int T;
    read(T);
    while (T--) {
        int n, m;
        read(n);
        read(m);
        memset(sum, 0, sizeof(sum));
        for (int i = 1; i <= n; ++i) {
            read(a[i]);
        }
        int u, v;
        for (int i = 1; i <= m; ++i) {
            read(u);
            read(v);
            modify(0, v, 1);
            modify(1, u, 1);
        }

        ll ans = 0LL;
        for (int i = 1; i <= n; ++i) {
            ans += gao1gao(query(1, i) - query(0, i - 1)) * a[i];
        }
        if (ans == 0) {
            puts("0");
            continue;
        }
        ll y = gao1gao(m);
        ll gcd = __gcd(ans, y);
        ans /= gcd;
        y /= gcd;
        if (y == 1LL) {
            printf("%lld\n", ans);
        } else {
            printf("%lld/%lld\n", ans, y);
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值