ZOJ 4062 Plants vs. Zombies(二分答案)
题目链接:Plants vs. Zombies
题意:从1到n每个位置一棵植物,植物每浇水一次,增加ai高度。人的初始位置为0,人每次能往左或往右走一步,走到哪个位置就浇水一次。求m步走完后最低高度的植物最大高度为多少。
题解:明显二分答案的题目。check时从左往右遍历,贪心思路:把该位置满足同时给后面减少浇水次数,策略是该位置和后一个位置左右横跳,注意最后一个位置的时候,如果满足就不需要再跳过去。
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 using namespace std; 6 7 const int N=1e5+10; 8 typedef long long ll; 9 ll a[N],d[N],n,m; 10 11 bool check(ll k){ 12 for(ll i=1;i<=n;i++) d[i]=0; 13 ll cnt=m; 14 for(ll i=1;i<=n;i++){ 15 if(cnt==0){ 16 if(i==n&&d[i]>=k) return true; 17 return false; 18 } 19 cnt--; 20 d[i]+=a[i]; 21 if(d[i]<k){ 22 ll tmp=k-d[i]; 23 ll c=tmp/a[i]; 24 if(tmp%a[i]!=0) c++; 25 if(cnt>=2*c){ 26 cnt-=2*c; 27 d[i]+=(a[i]*c); 28 d[i+1]+=(a[i+1])*c; 29 } 30 else return false; 31 } 32 } 33 return true; 34 } 35 36 int main(){ 37 int t; 38 scanf("%d",&t); 39 40 while(t--){ 41 ll ans=0; 42 scanf("%lld%lld",&n,&m); 43 for(ll i=1;i<=n;i++){ 44 scanf("%lld",&a[i]); 45 } 46 ll l=0,r=1e17+100; 47 while(l<=r){ 48 ll mid=(l+r)/2; 49 if(check(mid)) ans=max(ans,mid),l=mid+1; 50 else r=mid-1; 51 } 52 printf("%lld\n",ans); 53 } 54 55 return 0; 56 }