题意:
一条横轴上有n棵植物,第i棵植物在位置i上,生长速度为di,初始高度都为0,你的家在位置0上
你有一个洒水车,第0秒时在家门口(位置0),之后它每1秒都可以往左或往右移动一个单位(往左往右自己定,但必须移动),如果当前洒水车在位置i上,那么位置i的植物就会长高di厘米,请问在m秒内,所有植物高度最低的那棵植物最高能有多高
思路:
二分没错了,
每次验证先求出每棵植物要浇多少次水,然后从左往右扫过去就行了,注意以下几点:
- 如果当前这棵植物要浇很多次水,那么右左右左右左不停鬼畜就行了
- 如果当前位置右边没有任何植物,直接结束!(这是个坑)
- 中间过程处理不好可能会爆long long
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<map>
#include<string>
#include<math.h>
#include<queue>
#include<stack>
#include<iostream>
using namespace std;
#define LL long long
#define mod 1000000007
int n;
LL d[100005], ned[100005];
LL Jud(LL len)
{
int i, last;
LL ans = 0;
for(i=1;i<=n;i++)
ned[i] = (len+d[i]-1)/d[i];
last = n;
while(ned[last]==0 && last>=1)
last--;
for(i=1;i<=last;i++)
{
if(i==last && ned[i]<=0)
break;
ans++, ned[i]--;
if(ned[i]>=1)
{
ans += ned[i]*2;
ned[i+1] -= ned[i];
ned[i] = 0;
}
if(ans>=1e12+5) //防止爆long long
return ans;
}
return ans;
}
int main(void)
{
int T, i;
LL k, l, r, m;
scanf("%d", &T);
while(T--)
{
scanf("%d%lld", &n, &k);
for(i=1;i<=n;i++)
scanf("%lld", &d[i]);
l = 0, r = 1e18;
while(l<r)
{
m = (l+r+1)/2;
if(Jud(m)<=k)
l = m;
else
r = m-1;
}
printf("%lld\n", r);
}
return 0;
}