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): 156    Accepted Submission(s): 54


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(1i<j<km) , 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 .

1T10 .

1n,m50000 .

1wi5 .

1lirin .
 

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)
 

Recommend
hujie   |   We have carefully selected several similar problems for you:   5421  5420  5418  5417  5416 
题意,给出n个点,m个区间,先出三个区间,左值取最大,右值取最小,区间和的期望。

考虑每一个点,对结果的影响,如果,一个点包括了x个区间,那么,就有C(x,3)个w[i]在分子上,分母为C(m,3);所以最终的问题就是要求每个点,所点的区间数,真接用区间的开头加1,结尾减1,复杂度为o(n ),如果用线段树成段更新,复杂度为o(n * log(n);注意不要爆了long long,所以分子分母先都除上6.

第一种方法

#define N 300005
#define M 100005
#define maxn 205
#define SZ 26
#define MOD 1000000000000000007
#define lson (now<<1)
#define rson (now<<1|1)
int n,T,m,w[N],a,b,num[N],pri[N][2];
int main()
{
    while(S(T)!=EOF)
    {
        while(T--){
            S2(n,m);
            For(i,1,n+1){
                scan_d(a);
                w[i] = a;
                num[i] = 0;
                pri[i][0] =  pri[i][1] = 0;
            }
            FI(m){
                scan_d(a);scan_d(b);
                pri[a][0]++;
                pri[b][1]++;
            }
            int nn = 0;
            for(int i = 1;i<=n;i++){
                nn += pri[i][0];
                num[i] = nn;
                nn -= pri[i][1];
            }
            ll ans = 0,s2 = (ll)(m) * (ll)(m - 1) * (ll)(m -2) / 6;
            For(i,1,n+1){
                ll t = (ll) num[i];
                if(t >= 3){
                    ans += (ll)t * (ll)(t - 1) * (ll)(t - 2) * (ll)w[i] / 6;
                }
            }
            if(ans == 0){
                printf("%lld\n",ans);
                continue;
            }
            ll gc = gcd(ans,s2);
            ans /= gc;s2 /= gc;
            if(s2 == 1)
                printf("%lld\n",ans);
            else
                printf("%lld/%lld\n",ans,s2);
        }
    }
    //fclose(stdin);
    //fclose(stdout);
    return 0;
}


第二种方法(线段树)

#define N 300005
#define M 100005
#define maxn 205
#define SZ 26
#define MOD 1000000000000000007
#define lson (now<<1)
#define rson (now<<1|1)
int n,T,m,w[N],a,b;
struct node{
    int sum;
};
node tree[N*4];
void pushDown(int now){
    if(tree[now].sum > 0){
        tree[lson].sum  += tree[now].sum;
        tree[rson].sum += tree[now].sum;
        tree[now].sum = 0;
    }
}
void buildTree(int l,int r,int now){
    tree[now].sum = 0;
    if(l >= r){
        return ;
    }
    int mid = (l+r)>>1;
    buildTree(l,mid,lson);
    buildTree(mid+1,r,rson);
}
void updateTree(int l,int r,int now,int s,int e,int c){
    if(s <= l && e>= r){
        tree[now].sum += c;
        return ;
    }
    pushDown(now);
    int mid = (l+r)>>1;
    if(s <= mid) updateTree(l,mid,lson,s,e,c);
    if(e > mid) updateTree(mid+1,r,rson,s,e,c);
}
int queryTree(int l,int r,int now,int s,int e){
    if(s <= l && e>= r){
        return tree[now].sum;
    }
    pushDown(now);
    int mid = (l+r)>>1;
    if(s <= mid) return queryTree(l,mid,lson,s,e);
    if(e > mid) return queryTree(mid+1,r,rson,s,e);
    return 0;
}
int main()
{
    while(S(T)!=EOF)
    {
        while(T--){
            S2(n,m);
            buildTree(1,n,1);
            For(i,1,n+1){
                scan_d(a);
                w[i] = a;
            }
            FI(m){
                scan_d(a);scan_d(b);
                updateTree(1,n,1,a,b,1);
            }
            ll ans = 0,s2 = (ll)(m) * (ll)(m - 1) * (ll)(m -2) / 6;
            For(i,1,n+1){
                ll t = (ll) queryTree(1,n,1,i,i);
                if(t >= 3){
                    ans += (ll)t * (ll)(t - 1) * (ll)(t - 2) * (ll)w[i] / 6;
                }
            }
            if(ans == 0){
                printf("%lld\n",ans);
                continue;
            }
            ll gc = gcd(ans,s2);
            ans /= gc;s2 /= gc;
            if(s2 == 1)
                printf("%lld\n",ans);
            else
                printf("%lld/%lld\n",ans,s2);
        }
    }
    //fclose(stdin);
    //fclose(stdout);
    return 0;
}


你可能感兴趣的:(hdu 5419 Victor and Toys 线段树成段更新)