Atcoder ABC144E Gluttony

[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;
}

posted @ 2024-03-24 23:14  j1hx  阅读(46)  评论(0)    收藏  举报