The 2016 ACM-ICPC Asia China-Final Contest Promblem D
显然答案具有单调性,可以二分。问题是 我们二分出一个 堆数,该怎么判定能否达到这个堆数呢?
我们可以很简单的用调整法证明,最底下的一层的冰淇淋肯定是最小的那些,往上叠加的话我们再贪心的让较少的放在较小的上面,答案总不会更劣。
于是就口胡完了2333
#include<bits/stdc++.h> #define ll long long using namespace std; const int maxn=300005; int T,n,k,now,ans,L,R,mid,pre,N; ll a[maxn],num[2][maxn]; inline ll read(){ ll x=0; char ch=getchar(); for(;!isdigit(ch);ch=getchar()); for(;isdigit(ch);ch=getchar()) x=x*10ll+ch-'0'; return x; } inline bool can(){ N=1,pre=0,now=1; for(int i=1;i<=mid;i++) num[now][i]=a[N++]; for(int i=2;i<=k;i++){ pre=now,now^=1; for(int j=1;j<=mid;j++){ while(N<=n&&a[N]<2ll*num[pre][j]) N++; if(N>n) return 0; num[now][j]=a[N++]; } } return 1; } inline void solve(){ ans=0,scanf("%d%d",&n,&k); for(int i=1;i<=n;i++) a[i]=read(); sort(a+1,a+n+1); L=0,R=n/k; while(L<=R){ mid=L+R>>1; if(can()) ans=mid,L=mid+1; else R=mid-1; } printf("%d\n",ans); } int main(){ scanf("%d",&T); for(int i=1;i<=T;i++){ printf("Case #%d: ",i); solve(); } return 0; }
我爱学习,学习使我快乐