HDU 5419——Victor and Toys——————【线段树|差分前缀和】

Victor and Toys

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 262144/131072 K (Java/Others)
Total Submission(s): 654    Accepted Submission(s): 219

Problem Description

Victor has n toys, numbered from 1 to n. The beauty of the i-th toy is wi.

Victor has a sense of math and he generates m intervals, the i-th interval is [li,ri]. He randomly picks 3 numbers i,j,k(1≤i<j<k≤m), and selects all of the toys whose number are no less than max(li,lj,lk) and no larger than min(ri,rj,rk). Now he wants to know the expected sum of beauty of the selected toys, can you help him?

Input

The first line of the input contains an integer T, denoting the number of test cases.

In every test case, there are two integers n and m in the first line, denoting the number of the toys and intervals.

The second line contains n integers, the i-th integer wi denotes that the beauty of the i-th toy.

Then there are m lines, the i-th line contains two integers li and ri.

1≤T≤10.

1≤n,m≤50000.

1≤wi≤5.

1≤li≤ri≤n.

Output

Your program should print T lines : the i-th of these denotes the answer of the i-th case.

If the answer is an integer, just print a single interger, otherwise print an irreducible fraction like p/q.

Sample Input

1

3 4

1 1 5

2 3

1 3

3 3

1 1

Sample Output

5/4

Source

BestCoder Round #52 (div.2)

题目描述:

解题思路1:(差分前缀和)预处理出来s[i]数组,表示每个玩具在多少个区间内。E=sigma(xi*pi)。这里的xi就是有趣值,pi就是C(s[i],3)/C(m,3)。所以这道题关键是处理出来s[i]。同时注意姿势优美,别爆long long。至于差分前缀和,其实是处理离线区间问题的一个巧妙数组应用,对于m个区间,在区间左端点li的地方+1,在区间右端点ri的地方-1。最后前缀和处理, n 的复杂度就能得到第i个玩具在多少个区间内。

#include<bits/stdc++.h>
using namespace std;
typedef __int64 INT;
const int maxn=55000;
int a[maxn],s[maxn];
INT cal(INT nn){
    if(nn<3)
        return 0;
    return (nn-2)*(nn-1)*nn/6;
}
INT GCD(INT a,INT b){
    return b==0?a:GCD(b,a%b);
}
int main(){
    int t,n,m,li,ri;
    scanf("%d",&t);
    while(t--){
        memset(s,0,sizeof(s));
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        for(int i=1;i<=m;i++){  //差分
            scanf("%d%d",&li,&ri);
            s[li]++;s[ri+1]--;
        }
        for(int i=1;i<=n;i++){  //前缀和。s数组中的值就是第i个玩具在多少个区间内。
            s[i]+=s[i-1];
        }
        INT fm,fz;
        fz=0;
        for(int i=1;i<=n;i++){
            fz+=cal((INT)s[i])*a[i];
        }
        if(m<3){
            puts("0");
            continue;
        }
        fm=cal(m);
        if(fz==0){
            printf("0\n",fm);
        }else {
            INT gcd=GCD(fz,fm);
            fz/=gcd,fm/=gcd;
            if(fm==1)
                printf("%I64d\n",fz);
            else
            printf("%I64d/%I64d\n",fz,fm);
        }
    }
    return 0;
}

  

时间: 2024-08-06 19:49:34

HDU 5419——Victor and Toys——————【线段树|差分前缀和】的相关文章

hdu 1754 I Hate It 线段树 点修改

// hdu 1754 I Hate It 线段树 点修改 // // 不多说,裸的点修改 // // 继续练 #include <algorithm> #include <bitset> #include <cassert> #include <cctype> #include <cfloat> #include <climits> #include <cmath> #include <complex> #i

HDU 4902 Nice boat(线段树 区间更新)

Nice boat 大意:给你一个区间,每次可以进行两种操作,1:把区间中的数全都变成x  2:把区间中大于x的数变成gcd(a[i], x),最后输出序列. 思路:线段树成段更行,用num数组的叶子存储数据,节点当作lazy来使用. 1 #include <stdio.h> 2 const int maxn = 100005; 3 4 int num[maxn<<2]; 5 6 int gcd(int a, int b){ 7 return b?gcd(b, a%b):a; 8

hdu 4893 Wow! Such Sequence!(线段树)

题目链接:hdu 4983 Wow! Such Sequence! 题目大意:就是三种操作 1 k d, 修改k的为值增加d 2 l r, 查询l到r的区间和 3 l r, 间l到r区间上的所以数变成最近的斐波那契数,相等的话取向下取. 解题思路:线段树,对于每个节点新增一个bool表示该节点以下的位置是否都是斐波那契数. #include <cstdio> #include <cstring> #include <cstdlib> #include <algor

hdu 2852 KiKi&#39;s K-Number (线段树)

hdu 2852 题意: 一个容器,三种操作: (1) 加入一个数 e (2) 删除一个数 e,如果不存在则输出 No Elment! (3) 查询比a大的数中的第k小数,不存在就输出 Not Find! 解法: 关于第三点,可以先查询小于等于a的数的个数cnt,然后直接查询第cnt+k小数就行了 . 二分+树状数组 或者 主席树(有点杀鸡用牛刀的感觉 ...) 也是可以做的  _(:з」∠)_ code:线段树 1 #include <iostream> 2 #include <cst

Bestcoder round #65 &amp;&amp; hdu 5592 ZYB&#39;s Premutation 线段树

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 175    Accepted Submission(s): 74 Problem Description ZYB has a premutation P,but he only remeber the reverse log of each prefix of the premutat

hdu 1166 敌兵布阵 线段树 点更新

// hdu 1166 敌兵布阵 线段树 点更新 // // 这道题裸的线段树的点更新,直接写就可以了 // // 一直以来想要进线段树的坑,结果一直没有跳进去,今天算是跳进去吧, // 虽然十分简单,十分的水,继续加油 #include <algorithm> #include <bitset> #include <cassert> #include <cctype> #include <cfloat> #include <climits

HDU 1698 Just a Hook (线段树,区间更新)

Just a Hook Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 17214    Accepted Submission(s): 8600 Problem Description In the game of DotA, Pudge’s meat hook is actually the most horrible thing f

HDU 4107 Gangster Segment Tree线段树

这道题也有点新意,就是需要记录最小值段和最大值段,然后成段更新这个段,而不用没点去更新,达到提高速度的目的. 本题过的人很少,因为大部分都超时了,我严格按照线段树的方法去写,一开始居然也超时. 然后修补了两个地方就过了,具体修改的地方请参看程序. 知道最大值段和最小值段,然后修补一下就能过了.不是特别难的题目. #include <stdio.h> #include <string> #include <algorithm> using namespace std; c

HDU 1556 Color the ball 线段树

HDU 1556 Color the ball 线段树模版题,存个模板 1 #include <iostream> 2 #include <cstdio> 3 #include <fstream> 4 #include <algorithm> 5 #include <cmath> 6 #include <deque> 7 #include <vector> 8 #include <queue> 9 #inclu