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;
}

浙公网安备 33010602011771号