题目传送门

题目大意:有n个植物排成一排,标号为1-n,每株植物有自己的生长速度ai,每对植物浇一次水,该株植物就长高ai,现在机器人从第0个格子出发,每次走一步,不能停留,每一步浇一次水,总共可以走m步,问最矮的植物最高是多少。

思路:

  一般此类最小值最大问题都是二分,此题显然也是可以二分植物的高度的。

  确定某一个高度后,也确定了每个植物需要浇几次水,而对于一株植物来说,应当尽可能的在这株植物和后面那个格子来回走,是这株植物迅速超过最低高度(这样的走法是最优的,因为可以想象,如果往后走很多步再走回来,中间浪费的可能性比较大),于是就是对n个植物模拟浇水,考虑一些细节就可以了(二分跳出条件,long long等等)

//#pragma comment(linker,"/STACK:102400000,102400000")
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<vector>
#include<map>
#include<set>
#include<cstring>
#include<cmath>
#include<queue>
#include<stack>
#include<stdlib.h>
//#include<unordered_map>
#define lson l,mid,rt<<1
#define rson mid+1,r,(rt<<1)|1
#define CLR(a,b) memset(a,b,sizeof(a))
#define mkp(a,b) make_pair(a,b)
typedef long long ll;
using namespace std;
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;}
const int maxn=100010;
int n;
ll a[maxn],c[maxn],m;
inline bool judge(ll high){
    CLR(c,0);
    ll temp=m;
    if(m==0)return false;
    c[1]=a[1],m--;
    int i=1;
    for(;i<=n;i++)
    {
        if(m<=0)break;
        if(c[i]>=high)
        {
            if(m>0)
            {
            c[i+1]=a[i+1];
            m--;
            continue;
            }else{
                break;
            }
        }
        ll tmp=(ll)ceil((high-c[i])*1.0/a[i]);
        if(m>2*tmp){
            m-=2*tmp+1;
            c[i]+=a[i]*tmp;
            c[i+1]+=a[i+1]*(tmp+1);
            continue;
        }else if(m==2*tmp){
            c[i]+=a[i]*tmp;
            c[i+1]+=a[i+1]*tmp;
            break;
        }else{
            break;
        }
    }
    m=temp;
    for(i=1;i<=n;i++)
    {
        if(c[i]<high)return false;
    }
    return true;
}
int main(){
    int t;
    cin>>t;
    while(t--)
    {
        cin>>n>>m;
        ll l=0,r=0,mid,ans;
        for(int i=1;i<=n;i++){
            a[i]=read();
            r=max(r,a[i]*m);
        }
        if(m==0){
            printf("0\n");
            continue;
        }
        
        while(l<=r)
        {
            mid=(l+r)>>1;
        //    printf("mid  %d\n",mid);
            if(judge(mid))
            {
                ans=mid;
                l=mid+1;
            }else{
                r=mid-1;
            }
        }
        printf("%lld\n",ans);
    }
} 
View Code

相关文章: