HDOJ 5419 Victor and Toys 树状数组



分母是一定的C(m,3) 树状数组求每个数可以在那些段中出现,若x出现在了s段中,分子加上w[x]*C(s,3)

Victor and Toys

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


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
 




/* ***********************************************
Author        :CKboss
Created Time  :2015年08月23日 星期日 14时23分47秒
File Name     :HDOJ5419.cpp
************************************************ */

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <cmath>
#include <cstdlib>
#include <vector>
#include <queue>
#include <set>
#include <map>

using namespace std;

typedef unsigned long long int LL;

const int maxn=50500;

/****************BIT***********************/

int n,m;
int w[maxn];
int l[maxn],r[maxn];

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

int tree[maxn];

void add(int p,int v)
{
	for(int i=p;i<maxn;i+=lowbit(i)) tree[i]+=v;
}

int sum(int p)
{
	int ret=0;
	for(int i=p;i;i-=lowbit(i)) ret+=tree[i];
	return ret;
}
	
LL getC(LL x)
{
	return x*(x-1)/2LL*(x-2)/3LL;
}

LL gcd(LL a,LL b)
{
	if(b==0) return a;
	return gcd(b,a%b);
}

int main()
{
	//freopen("in.txt","r",stdin);
	//freopen("out.txt","w",stdout);

	int T_T;
	scanf("%d",&T_T);
	while(T_T--)
	{
		scanf("%d%d",&n,&m);
		for(int i=1;i<=n;i++) scanf("%d",w+i);
		memset(tree,0,sizeof(tree));
		for(int i=0;i<m;i++)
		{
			scanf("%d%d",l+i,r+i);
			add(l[i],1); add(r[i]+1,-1);
		}

		if(m<3) { puts("0"); continue; }

		LL up=0,down=getC(m);
		for(int i=1;i<=n;i++)
		{
			LL x=sum(i);
			if(x>=3)
			{
				up=up+w[i]*getC(x);
			}
		}
		if(up==0) { puts("0"); continue; }

		LL g=gcd(up,down);
		if(g==down) cout<<up/g<<endl;
		else cout<<up/g<<"/"<<down/g<<endl;
	}
    
    return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值