题目链接: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<A2。
取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<A2<B1<B2 MIN=0
2.A1<B1<A2<B2 MIN=0
3.B1<A1<A2<B2 MIN=min(A1-B1,A2-B1)=A1-B1
4.A1<B1<B2<A2 MIN=min(A2-B2,A2-B1)=A2-B2
5.B1<A1<B2<A2 MIN=min(A1-B1+A2-B2,A2-B1)=A1-B1+A2-B2
6.B1<B2<A1<A2 MIN=A1-B1+A2-B2
发现没有啊,都对应的啊
所以就直接贪心就好啦。程序如下。
#include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cstdio> #include<vector> 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; }
原文地址:https://www.cnblogs.com/2014nhc/p/11751730.html
时间: 2024-11-09 09:48:08