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 n,m的数据范围在 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 1≤li≤n),然后依次把合法的(上文说的不再受 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;
}