[ABC144E]Gluttony 的题解

题目大意:

有两个数组 \(a_i\)\(f_i\),任意选取若干个 \(a_i\) 使他们一共减少的数量在不超过 \(k\) 的情况下,任意将 \(a\) 数组与 \(f\) 中的元素进行匹配,使两两间的乘积的最大值最小。

分析

首先考虑 \(k=0\) 的情况:对于任意的 \(a_i<a_j\)\(f_x<f_y\),可以发现 \(\max(a_i\times f_y,a_j\times f_x)\le \max(a_i\times f_y,a_j\times f_x)\)。所以将 \(a\) 数组升序排列,将 \(f\) 数组降序排列,一一对应就是最优的情况了。

因为减少的量越大获得乘积的最大值越小,所以这个问题具有单调性,可以使用二分进行求解。

可以二分乘积的最大值最小值,通过最小值与 \(f_i\) 求解出如果需要满足这个最小值 \(a_i\) 的最大值,计算出需要更改的数量,并判断是否小于 \(k\),即满足 \(\sum_{i=1}^n\lceil \frac{A_i \times F_i-x}{F_i} \rceil <k\)

AC Code

#include<bits/stdc++.h>
#define ceil(a,b) a/b+(a%b!=0)
#define int long long
using namespace std;
const int N=2e5+5;
int n,k,a[N],f[N],l=0,r=1e18,ans=-1,s[N];
bool cmp(int a,int b){
	return a>b;
}
bool ck(int x){
	int cnt=0;
	for(int i=1;i<=n;i++){
		int sb=a[i]*f[i];
		if(sb>x) cnt+=ceil((sb-x),f[i]);
	}
	return (cnt<=k);
}
signed main(){
	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+1+n),sort(f+1,f+1+n,cmp);
	while(l<=r){
		int mid=(l+r)/2;
		if(ck(mid)){
			r=mid-1;
			ans=mid;
		}else l=mid+1;
	}cout<<ans<<endl;
	return 0;
} 
posted @ 2024-07-14 13:35  未抑郁的刘大狗  阅读(17)  评论(0编辑  收藏  举报