Problem D. Ice Cream Tower(2016 China-Final)【二分答案+貪心檢驗】
阿新 • • 發佈:2019-02-14
source:題目連結
題意:這是2016 ACM-ICPC China-Final的D題,一共有N個冰淇淋球,做一個冰淇淋需要K個球,並且由於穩定性,這K個球還必須滿足上下相鄰的下面比上面大至少兩倍。先給出N個球的質量,問最多能做出多少個冰淇淋?
思路:最開始以為就是簡單的貪心,但是發現貌似不對,後來在現場題目講解時才知道要用二分答案的方法,也就是對可以做多少個冰淇淋m做二分,每次檢驗是否能做出m個冰淇淋。
檢驗標準是:首先對B[]排序後將前m個取出來作為m個冰淇淋的頂端,也就是A[]的前m個=B[]的前m個,之後選A[i]時,貪心地去找滿足B[p]>2×A[i-m]的B[p]作為A[i],這樣p最多就只跑一遍(線性),如果能構成表示檢驗返回結果成功,反之返回結果失敗。
程式碼如下:
#include<bits/stdc++.h> using namespace std; typedef long long LL; LL b[300005],a[300005]; int t,T,n,k; int judge(int m) //檢驗m個冰淇淋能否做出來 { for(int i=0;i<m;i++) a[i]=b[i]; int p=m; for(int i=m;i<m*k;i++) { while(b[p]<a[i-m]*2 && p<n) p++; if(p==n) return 0; a[i]=b[p]; p++; } return 1; } int Bisection(int l,int r) //二分答案 { while(l<r) { int mid=(l+r+1)/2; if(judge(mid)) l=mid; else r=mid-1; } return l; } int main() { scanf("%d",&T); for(t=1;t<=T;t++) { scanf("%d%d",&n,&k); for(int i=0;i<n;i++) scanf("%lld",&b[i]); sort(b,b+n); printf("Case #%d: %d\n",t,Bisection(0,n/k)); } return 0; }