题目大意:

有两个数组 aia_ifif_i,任意选取若干个 aia_i 使他们一共减少的数量在不超过 kk 的情况下,任意将 aa 数组与 ff 中的元素进行匹配,使两两间的乘积的最大值最小。

分析

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

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

可以二分乘积的最大值最小值,通过最小值与 fif_i 求解出如果需要满足这个最小值 aia_i 的最大值,计算出需要更改的数量,并判断是否小于 kk,即满足 i=1nAi×FixFi<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;
}