题目链接:https://vjudge.net/problem/ZOJ-4062
解题思路:
二分一个最小值,那么所有位置必定要大于等于这个值,那么就在一个位置上加满之后再向后面一定,一直横向左右跳的加就行了,直到终点在n或者n-1位置。
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <queue>
#include <time.h>
#define inf 0x3f3f3f3f
#define F(i,a,b) for(int i=a;i<=b;++i)
using namespace std;
typedef long long ll;
const int mx = 1e5 + 10;
int n,a[mx];
ll m,b[mx];
bool check(ll x,ll m)
{
for(int i=0;i<=n+1;i++) b[i] = 0;
int p = 0;
for(int i=1;i<=n;i++)
{
p++;
if(m<=0&&b[p]<x) return 0;
m--,b[p] += a[p];
if(x-b[p]>0){
ll cnt = (x-b[p]-1) / a[p] + 1;
if(m<2*cnt) return 0;
b[p] += cnt * a[p];
b[p+1] += cnt * a[p+1];
m -= 2*cnt;
}
}
return 1;
}
int main()
{
int t;
scanf("%d",&t);
while(t--){
scanf("%d%lld",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",a+i);
}
ll l = 0,r = 1e17;
while(l<r){
ll mid = (l+r+1)>>1;
if(check(mid,m)) l = mid;
else r = mid - 1;
}
printf("%lld\n",l);
}
return 0;
}