K - GukiZ hates Boxes (二分&贪心)
K - GukiZ hates Boxes
http://codeforces.com/problemset/problem/551/C
Professor GukiZ is concerned about making his way to school, because massive piles of boxes are blocking his way.
In total there are n piles of boxes, arranged in a line, from left to right, i-th pile (1 ≤ i ≤ n) containing ai boxes. Luckily, m students are willing to help GukiZ by removing all the boxes from his way. Students are working simultaneously. At time 0, all students are located left of the first pile. It takes one second for every student to move from this position to the first pile, and after that, every student must start performing sequence of two possible operations, each taking one second to complete. Possible operations are:
- If i ≠ n, move from pile i to pile i + 1;
- If pile located at the position of student is not empty, remove one box from it.
GukiZ's students aren't smart at all, so they need you to tell them how to remove boxes before professor comes (he is very impatient man, and doesn't want to wait). They ask you to calculate minumum time t in seconds for which they can remove all the boxes from GukiZ's way. Note that students can be positioned in any manner after t seconds, but all the boxes must be removed.
Input
The first line contains two integers n and m (1 ≤ n, m ≤ 105), the number of piles of boxes and the number of GukiZ's students.
The second line contains n integers a1, a2, ... an (0 ≤ ai ≤ 109) where ai represents the number of boxes on i-th pile. It's guaranteed that at least one pile of is non-empty.
Output
In a single line, print one number, minimum time needed to remove all the boxes in seconds.
说起来这题我去年就看到过就是没写出来。。
题意:
有一条道路,上面的一些位置有一些物体。有n名学生,他们可以自由行动,但是每次移动都需要消耗一单位的时间,与此同时,每搬一个物体也消耗学生一单位的时间。问最短需要多少时间可以搬完这些物体。
显而易见的,这是一个二分问题。让我们先令最后一个有木块的堆的位置为end(不可以直接使用n,因为不能保证最后几个堆是有木块的,即有效长度不一定n),初始的最大值没有异议就是一个人搬完所有的东西也就是∑a[i]+end,按照许多最大值的最小值问题的思路这里的最小值应该是无数学生搬完这些木块的时间,由于学生无数多所以搬木块的时间都抽象为0(实际上绝对不可能为0)因此学生所用的最小时间就是走到最后一个有效堆的时间,即end。然后再二分枚举出所需的时间,看是否符合条件,在其中找出最大值。
这里的检验用到了贪心的思想,在所需工时(把当前堆及之前的堆搬走所需的时间)大于所给的最大时间时,便派一名学生来搬运(这个学生可以搬走x-i个物件,即最大时间剪去走路时间),当所需工时小于所给的最大时间时便把这堆留着,向前继续遍历,直到所需工时大到再次需要学生前来搬时再一并搬动。如果最终可以搬完则可行
代码:
#include<algorithm>
#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<vector>
#include<stack>
#include<cmath>
#include<queue>
#include<set>
#include<map>
using namespace std;
const int size=1e5+5;
typedef long long LL;
#define md(x,y) (x+y)/2
int main()
{
LL arr[size];
int n,m;
while(cin>>n>>m)//n为盒子堆数,m为学生数
{
int i;
LL low=0,up=0,mid;
LL end;
for(i=0;i<n;i++)
{
cin>>arr[i];
if(arr[i]) end=i+1;
up+=arr[i];
}
//cout<<i<<' '<<n<<endl;
low=end;
up+=end;
while(low<=up)
{
mid=md(low,up);
LL stu=m,tim=0;
int flag=0;
for(i=0;i<end;i++)
{
tim+=arr[i];
while(tim+i+1>=mid)
{
tim-=(mid-i-1);
--stu;
if(stu<0) {
flag=1;
break;
}
}
}
if(stu==0)
{
if(tim>0) flag=1;
}
if(!flag)
{
up=mid-1;
}
else low=mid+1;
}
cout<<up+1<<endl;
}
return 0;
}
//
/*
2 1
1 1
3 2
1 0 2
4 100
3 4 5 4
*/