题解:二分加贪心,,,二分答案,然后进行判断,判断的时候,首先给每一组配一个最大的球,然后在向每一组里面填球,注意填球的时候要按组进行,每一组先填一个,然后更新每一组内的最小值,方便下一次寻找。
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=3E5+7; ll arr[N]; ll b[N]; bool mark[N]; int n,m; bool judge(int x){ int pos= n-1; for(int i=1;i<=x;i++) b[i]=arr[pos],pos--;//先给每一组添加一个底; for(int i=2;i<=m;i++){//每一组还需要m-1个 for(int j=1;j<=x;j++){ int flag=-1; ll x1=b[j]; x1>>=1; for(int k=pos;k>=0;k--){//在商店中剩余的物品里面挑选出第一个小于小于等于前一个的一半的物品 if(arr[k]<=x1){ flag=k; b[j] = arr[k]; pos=k-1;//更新一下pos break; } } if(flag==-1) return 0;//找不到的话直接返回0 } } return 1; } void solve(int xx){ scanf("%d%d",&n,&m); for(int i=0;i<n;i++) scanf("%lld",&arr[i]); sort(arr,arr+n); int l=0; int r=n; int ans=0; while(l<=r){ int mid=(l+r)/2; if(judge(mid)){ ans=max(ans,mid); l=mid+1; } else r=mid-1; } printf("Case #%d: %d\n",xx,ans); } int main(){ int t; cin>>t; for(int i=1;i<=t;i++) solve(i); return 0; }