P9889 [ICPC2018 Qingdao R] Plants vs. Zombies

原题链接

题解

千万要仔细读题呀!
解释一下为什么要和右边的植物来回走来长高:
对于第一个植物,肯定是往右边,对于第二棵植物,左边的植物已经达到高度了,右边可能达到了高度,也可能没有,往右边肯定是更优解

code

#define ll long long
#include<bits/stdc++.h>
using namespace std;

inline void read(ll &x) {
    x = 0;
    ll flag = 1;
    char c = getchar();
    while(c < '0' || c > '9'){
        if(c == '-')flag = -1;
        c = getchar();
    }
    while(c >= '0' && c <= '9') {
        x = (x << 3) + (x << 1) + (c ^ 48);
        c = getchar();
    }
    x *= flag;
}

inline void write(ll x)
{
    if(x < 0){
        putchar('-');
        x = -x;
    }
    if(x > 9)
        write(x / 10);
    putchar(x % 10 + '0');
}


ll a[100005]={0};
ll n,m;

ll check(ll mins)
{
    ll steps=m;
    ll b[n+5];

    for(int i=1;i<=n;i++)  b[i]=mins/a[i]+(mins%a[i]!=0);//把需要走多少次才能长高到mins高度

    int last=0;//为什么要设last变量?因为为了消除当前的b[i]的过程中,b[i+1]可能也顺便消除完了,这样一来i+1就不用走了
    //总结来说,如果之后的i都大于mins,就走都不用走了

    for(int i=1;i<=n;i++)//这一段算法的逻辑是为了消除当前的b[i]需要的steps
    {
        if(b[i]>0)//b[i]有可能小于零
        {
            steps-=(b[i]-1)*2+1+(i-last-1);//如果这个需要消除,从上一个需要消除的点赶过来
            b[i+1]-=b[i]-1;
            last=i;
        }

        if(steps<0)return 0;
    }

    return 1;
}
int main()
{
    ll t;
    read(t);
    while(t--)
    {
        read(n);
        read(m);

        ll l=0,r=2e17;
        for(ll i=1;i<=n;i++)
        {
            read(a[i]);
            r=min(r,a[i]*m);//mins最大不会超过这个值
        }

        while(l+1<r)
        {
            ll mid=((r-l)>>1)+l;
            if(check(mid)) l=mid;
            else r=mid;
        }
        write(l);
        putchar('\n');
    }
    return 0;
}

posted @   纯粹的  阅读(13)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~
点击右上角即可分享
微信分享提示