题意:
就是n个学生帮助教授搬箱子, 箱子分成m 堆, 每个学生每秒可以选择的两个操作
操作1,为从i堆迈向第i+1堆,
操作2,从i-1堆箱子中帮忙抱走一个箱子
问抱走所有箱子的最少时间为多少, 每个学生每秒可以同时行动
题解:
二分时间 然后再当前时间下,一个一个派出所有的学生,使其走到他能走的最远距离
代码:
#include<stdio.h>
int flag, value[100005], value2[100005], n, m;
void find(long long int mid)
{
long long int temp = mid, fla = 0;
temp --;
if(flag == n) return;
if(temp == 0) return;
while(1)
{
while(!value2[flag])
{
flag ++;
if(fla)temp --;
if(flag == n) return;
if(temp == 0) continue;
}
if(!fla) temp -= flag;
fla = 1;
if(value2[flag] <= temp)
{
temp -= value2[flag];
value2[flag] = 0;
if(flag == n - 1) flag ++;
if(flag == n) return;
if(temp == 0) continue;
flag ++, temp --;
if(flag == n) return;
if(temp == 0) continue;
}
else
{
value2[flag] -= temp;
return;
}
}
}
bool slove(long long int mid)
{
for(int i = 0; i < n; i++)
value2[i] = value[i];
flag = 0;
for(int i = 1; i <= m; i++)
{
find(mid);
if(flag == n) break;
}
if(flag == n) return 1;
return 0;
}
int main()
{
while(scanf("%d %d", &n, &m) != EOF)
{
long long int sum = 0;
for(int i = 0; i < n; i++)
scanf("%d", &value[i]), sum += value[i];
sum += n;
long long int l = 0, r = sum, mid, Ans = -1;
while(l <= r)
{
mid = (r+l)/2;
if(slove(mid))
{
r = mid - 1;
Ans = mid;
}
else l = mid + 1;
}
printf("%lld\n", Ans);
}
}