以二分算法枚举答案的方法非常高效,枚举所需的时间复杂度只需O(logN)
设x为答案,check(x)只有真假两种取值。
能够使用二分枚举算法的条件:
存在一个X,当x小于X时和x大于X时,check(x)真假值不一样。
二分枚举即能够找出真假之间的边界,这个就是所求在满足题意下的最值了。
如果x是浮点数,那么边界的取值注意精度即可。
const double eps=1e-7; while(l+eps<r) { mid=(l+r)/2; if(check(mid)) l=mid; else r=mid; }
如果x是整数,那么注意所求,是真值区的最大值还是最小值,见例题。
例题:https://www.nowcoder.com/acm/contest/52/E
AC代码:
#include<iostream> #include<algorithm> using namespace std; int c[10005],v[10005]; long long p[10005]; int n,k; bool check(int x) { for(int i=0;i<n;i++) p[i]=v[i]-x*c[i]; sort(p,p+n); long long sum=0; for(int i=n-1;i>=n-k;i--) sum+=p[i]; return sum>=0; } int main() { int T; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&k); for(int i=0;i<n;i++) scanf("%d%d",&c[i],&v[i]); int l=0,r=100000,mid,res; while(l<=r) { mid=(l+r)/2; if(check(mid)) { res=mid; l=mid+1; } else r=mid-1; } printf("%d ",res); } return 0; }