Balanced Diet(前缀数组,转化)

Balanced Diet
(读题很重要看了半天读错题意没看见maximum我晕鼓7
题意:
给定 n n n个糖,每个只能用一次,在 n n n行输入中包含了 a i   b i a_i\ b_i ai bi分别表示这个糖的贡献和他的类型。类型取值范围为 [ 1 , m ] [1,m] [1,m]
给定数组 l n l_n ln表示如果选择类型 i i i,那么总共的糖果个数 p i p_i pi应该大于 l i l_i li,当然也可以选择不选。
S C \frac{S}{C} CS的最大值,这里 S S S表示选择的糖果的 s u m ( a i ) sum(a_i) sum(ai) C C C表示选择的糖果类型中的 m a x ( p i ) max(p_i) max(pi)
思路:
最简单的思路是对于所有可以选择的糖果而言, a i a_i ai肯定是从大到小选择,这里必然要排序。因为 n , m n,m nm的数据范围在 1 0 8 10^8 108,考虑到还有不同的类型造成限制条件,所以开vector进行排序。
可以想到如果有一个最大的数量已经被选中,那么对于所有不再受 l i l_i li限制的糖果而言,他们的加入不再对 C C C产生贡献,肯定有多少来多少。
然后就是 l i l_i li这个限制因素的解决。因为已经知道对于每个类型内部而言, a i a_i ai必然从大到小排序依次进入,所以可以遍历分母 C C C的可能大小(1~n,因为 1 ≤ l i ≤ n 1\le l_i \le n 1lin),然后依次把合法的(上文说的不再受 l i l_i li限制) a i a_i ai进行加入,维护一个最大值就可。
代码如下:

vector<LL> cun[maxn], dp[maxn];
LL n, m;
LL l[maxn];
bool Cmp(  int  a,  int b) {
    
    
	return a > b;
}
struct fenshu {
    
    
	LL zi, mu;
}ans, tt;
bool big(fenshu a, fenshu b) {
    
    
	return a.zi*b.mu > a.mu*b.zi;
}
int main() {
    
    
	LL T, tup, tdown;
	LL a, b;
	int co;
	scl(T);
	//T = 1;
	while (T--) {
    
    
		co = 0; tup = 0; tdown = 0;
		ans.zi = 0; ans.mu = 1;
		tt.zi = 0; tt.mu = 0;
		scl(n); scl(m);
		for (int i = 1; i <= m; i++)scl(l[i]);
		for (int i = 1; i <= n; i++) {
    
    
			scl(a); scl(b);
			cun[b].push_back(a);
		}
		for (int i = 1; i <= m; i++) {
    
    
			sort(cun[i].begin(), cun[i].end(), Cmp);
			for (int j = 0; j < cun[i].size(); j++) {
    
    
				tup = max(1ll*j + 1, l[i]);
				dp[tup].push_back(cun[i][j]);
			}
			cun[i].clear();
		}
		for (int i = 1; i <= n; i++) {
    
    
			for (int j = 0; j < dp[i].size(); j++) {
    
    
				tt.zi += dp[i][j];
			}
			tt.mu = i;
			if (big(tt, ans)) {
    
    
				ans.mu = tt.mu; ans.zi = tt.zi;
			}
			dp[i].clear();
		}
		tdown = lgcd(ans.mu, ans.zi);
		printf("%lld/%lld\n", ans.zi / tdown, ans.mu / tdown);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_44986601/article/details/108982322
今日推荐