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 }
View Code

 

posted @ 2018-11-17 17:59  pavtlly  阅读(315)  评论(0编辑  收藏  举报