题意:
你的房子在0点,1,2,3,...,n(n<=1e5)点每个点都有一颗高度为0的花,浇一次水花会长a[i]。
你有一个机器人刚开始在你家,最多走m步,每一步只能往前走或者往后走,每走到一个地方除了房子都会给花浇水,问m步以后最低那朵花的高度最大是多少。
思路:二分,并且可以证明左右横跳(即这一个点不够我们就来回走一直到够高度为止)。
需要注意步数用完直接break,每一朵花浇够次数立刻走向下一朵花(如果还有步数)。
代码:
#include<bits/stdc++.h> #define ll long long #define maxn 200010 using namespace std; ll n,m,k; ll c[maxn],a[maxn]; ll ans,tmp,sum; inline ll read(){ ll x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9'){ if(ch=='-') f=-1; ch=getchar(); } while(ch>='0'&&ch<='9'){ x=x*10+ch-'0'; ch=getchar(); } return x*f; } inline void print(ll x){ if(x<0){ putchar('-'); x=-x; } if(x>9) print(x/10); putchar(x%10+'0'); } bool jud(ll mid) { for(int i=1;i<=n;i++) c[i]=0; ll cnt=m-1;c[1]=a[1]; int i=1; for(;i<=n;i++) if(i<n){ if(cnt==0) break; ll tmp=(mid-c[i]+a[i]-1)/a[i]; if(tmp<=0) {cnt--;c[i+1]+=a[i+1];continue;} if(cnt<tmp*2) break; cnt-=tmp*2; c[i]+=a[i]*tmp; c[i+1]+=a[i+1]*tmp; if(cnt==0) break; cnt--; c[i+1]+=a[i+1]; if(cnt==0) break; } else { if(cnt==0) break; if(c[i]>=mid) break; else { ll tmp=(mid-c[i]+a[i]-1)/a[i]; if(cnt<tmp*2) return 0; else c[i]+=a[i]*tmp; } } for(;i<=n;i++)if(c[i]<mid) return 0; return 1; } int main() { ll T,cas=1; T=read(); while(T--) { n=read();m=read(); ll l=0,r=m; for(int i=1;i<=n;i++) {a[i]=read(); if(r<m*a[i]) r=m*a[i]; } if(m==0) {puts("0");continue;} ll ans=r; while(l<r) { ll mid=(l+r)/2; if(jud(mid)) {l=mid+1;ans=mid;} else r=mid; } print(ans); putchar(' '); } return 0; }