题目链接:https://atcoder.jp/contests/abc144/tasks/abc144_e
一道很简单的二分加贪心,但我在比赛时没过。因为我输入错了,它竟然加上样例还有6个点是对的,于是我查了半小时都没发现这件事,到最后只能怀疑是自己想法错了放弃。
(我不管我不管,是数据的锅!)至于难度的话应该有T1无T2吧
首先二分答案sum。
现在的问题是你要将A,F数组一一对应,如果A[i]*F[i]>SUM,K-=A[i]-SUM/F[i],看K最后是否小于0。
然后你就会发现其实只要把A 从小到大,F从大到小排序,然后算出来的就是最优解
为什么呢?我们可以取两个数来试试。
取A1,A2,A1
取B1=SUM/F1,B2=SUM/F2,F1>F2。
减去的数很显然越小越好,所以减去的数为MIN(max(0,A1-B1)+max(0,A2-B2),max(0,A1-B2)+max(0,A2-B1))
总共有六种情况,分别为
1.A1
2.A1
3.B1
4.A1
5.B1
6.B1
发现没有啊,都对应的啊
所以就直接贪心就好啦。程序如下。
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
int n,he;
ll a[1000009],b[1000009];
ll ans=0;
bool check(ll sum,ll k)
{
he=1;
for (int i=n;i>=1;i--)
{
if (a[he]*b[i]<=sum) {he++;continue;}
if ((a[he]-sum/b[i])>k) return false;
k-=a[he]-sum/b[i];
he++;
}
return true;
}
int main()
{
ll k;
scanf("%d%lld",&n,&k);
for (int i=1;i<=n;i++) scanf("%lld",&a[i]);
for (int i=1;i<=n;i++) scanf("%lld",&b[i]);
sort(a+1,a+1+n); sort(b+1,b+1+n);
ll l=0,r=0;
r=b[n]*a[n];ans=r;
while (l<=r)
{
ll mid=(l+r)/(ll)2;
if (check(mid,k)) ans=mid,r=mid-1;
else l=mid+1;
}
printf("%lld\n",ans);
return 0;
}