[ABC144E] Gluttony
题面翻译
【题目描述】
高桥君参加大胃王比赛。比赛由 \(N\) 人组成的团队为基本单位参赛,高桥君的队伍的队员从 \(1\sim N\) 编号。第 \(i\) 名队员的消化代价为 \(A_i\)。
比赛有 \(N\) 种不同的食物,每位队员需要负责吃掉其中一种食物,不能有两名队员吃同一种食物,也不能让一名队员吃多与一种食物。第 \(j\) 种食物的难吃程度为 \(F_j\)。 消化代价 \(x\) 的队员吃完难吃程度 \(y\) 的食物需要花费 \(x\times y\) 秒。 整个队伍的成绩是 \(N\) 名队员吃完食物花费时间的最大值。
比赛前,高桥君的队伍会进行修行。一次修行可以将一名消化代价大于 \(0\) 的队员的消化代价减少 \(1\)。由于修行需要消耗庞大的食费,因此最多只能进行 \(K\) 次修行。
通过修行和适当选择每位队员吃的食物,高桥队在比赛中能够获得的最好成绩是多少?
【输入格式】
第 \(1\) 行,两个正整数 \(N,K\)。
第 \(2\) 行,\(N\) 个正整数 \(A_1,A_2,\cdots,A_N\)。
第 \(3\) 行,\(N\) 个正整数 \(F_1,F_2,\cdots,F_N\)。
【输出格式】
输出高桥队的最好成绩。
样例 #1
样例输入 #1
3 5
4 2 1
2 3 1
样例输出 #1
2
样例 #2
样例输入 #2
3 8
4 2 1
2 3 1
样例输出 #2
0
样例 #3
样例输入 #3
11 14
3 1 4 1 5 9 2 6 5 3 5
8 9 7 9 3 2 3 8 4 6 2
样例输出 #3
12
思路
以下简称消化代价为a,难吃程度为f.
样例是好样例,通过简单归纳,发现要把a大的乘上f小的,a小的则要乘f大的,这样能使\(\sum_{i = 1}^{n} a_i f_j,0≤i≤n,0≤j≤n,i+j=n\)最小,即最优解。于是将a数组sort成升序,而f组与a组刚好相反,所以降序。
但是,这N个人还可以进行K次修改,怎么办呢?我们考虑二分消化时间最小值x。当\(a_i f_j<t\)时,将\(a_i f_j - t\),再取它整除\(f_j\)的结果,即\(训练过的 a_i\),此时的\(a_i f_j < t\),即满足答案x的结果。
代码
#include<bits/stdc++.h>
using namespace std;
int a[200005],f[200005];
long long n,k;
bool cmp(int &x,int &y)
{
return x>y;
}
bool check(long long x)
{
long long sum=0;
for(int i=1;i<=n;i++)
{
if(1ll*a[i]*f[i]>x)
{
sum+=(1ll*a[i]*f[i]-x+f[i]-1)/f[i];
}
}
return sum<=k;
}
int main()
{
ios::sync_with_stdio(false);
cin>>n>>k;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
for(int i=1;i<=n;i++)
{
cin>>f[i];
}
sort(a+1,a+n+1);
sort(f+1,f+n+1,cmp);//降序排列
long long l=0,r=1e12+5,ans=0;
while(l<=r)
{
long long mid=(l+r)/2;
if(check(mid))
{
ans=mid;
r=mid-1;
}
else
{
l=mid+1;
}
}
cout<<ans<<endl;
return 0;
}
标签:Atcoder,Gluttony,ABC144E,int,sum,队员,样例,long,食物
From: https://www.cnblogs.com/j1hx-oi/p/18093326