The 13th Chinese Northeast Contest B. Balanced Diet(前缀和)

题目描述

Taylor is wandering in a milk candy store. The store has m types of sweets and there are n sweets in the store. The i-th sweet has the value of ai, and it is of type bi.
Taylor is planning to buy some sweets in the store, each sweet can be bought at most once. He will buy at least one sweet. Taylor knows that a balanced diet is important, the value of a sweet set is measured as S/C, where S denotes the sum of ai and C denotes the maximum number of occurrences among all types of sweets.
Assume Taylor selects pi sweets of type i, it is not welcomed if 1≤pi Please write a program to help Taylor find the sweet set with maximum value.

Input

The first line of the input contains an integer T(1≤T≤1000), denoting the number of test cases.
In each test case, there are two integers n,m(1≤n,m≤100000) in the first line, denoting the number of sweets and types.
In the second line, there are m integers l1,l2,…,lm(1≤li≤n).
For the next n lines, each line contains two integers ai,bi(1≤ai≤108,1≤bi≤m), denoting each sweet.
It is guaranteed that ∑n≤106 and ∑m≤106, and there always exists a valid sweet set.

Output

For each test case, print a single line of format u/v, denoting the maximum value uv. Note that you should guarantee that gcd(u,v)=1.

Example

Input
2
2 1
2
7 1
2 1
3 2
1 2
2 1
5 2
3 2
Output
9/2
5/1

题目大意

给出了n和m,表示有m种类型的糖果,这些糖果一共n个。
接下了是m个数,表示如果你选了第 i 种糖果,那么你最少选 Li (你也可以不选)
再接下来就是 n 行数据,每一行 a[i] 和 b[i] 表示这个糖果属于 bi 这个种类的,它的价值是a[i]。
最后让你输出你挑选的糖果的总价值除以 你取得糖果中数量最多的那种糖果的数量,然后化成最简分数。

题目分析

num[i] //表示第i种糖果最少选多少个
用邻接表st[b] //表示b类的糖果有哪些,并记录其价值
邻接表g[i] //表示选取糖果数量最多的那一种数量为i时,与i-1相比,多选择了哪一些糖果,并记录其价值

然后前缀和处理g[i],并记录最大的 s u m ( g [ 1 − i ] ) / i sum(g[1-i])/i sum(g[1i])/i 即可。(思路不太好说,看代码吧)

代码如下
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define LL long long
#define ULL unsigned long long
#define PII pair
#define PDD pair
#define x first
#define y second
using namespace std;
const int N=1e5+5,INF=1e9+7;
int num[N];
vector<int> st[N],g[N];
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		for(int i=0;i<N;i++) st[i].clear(),g[i].clear();
		int n,m;
		scanf("%d%d",&n,&m);
		for(int i=1;i<=m;i++) scanf("%d",&num[i]);
		for(int i=1;i<=n;i++)
		{
			int a,b;
			scanf("%d%d",&a,&b);
			st[b].push_back(a);			//维护邻接表st[]
		}
		for(int i=1;i<=m;i++)
		{
			sort(st[i].begin(),st[i].end(),greater<int>());	//为了使获得的答案最大,应该让大的值往前排
			for(int j=0;j<st[i].size();j++)
				g[max(num[i],j+1)].push_back(st[i][j]);		//如果要选第i种糖果,那么至少要选num[i]种因此g[]的下标要从num[i]开始
		}
		LL sum=0,ans=0,k=1;			//sum记录前缀和,ans/k记录最大值
		for(int i=1;i<=n;i++)		//枚举最大数量i
		{
			for(int j=0;j<g[i].size();j++)		//将g[i]中的数全部加入sum
				sum+=g[i][j];
			
			if(1.0*ans/k<1.0*sum/i) ans=sum,k=i;//记录最大值
		}
		LL gcd=__gcd(ans,k);					//约分
		printf("%lld/%lld\n",ans/gcd,k/gcd);
	}
	return 0;
}

你可能感兴趣的:(Codeforces)