CF551C GukiZ hates Boxes 题解
本题算法:二分+贪心+模拟
直通CF551C
1.时间复杂度
-
如果暴力枚举 \(O(n)=n^2\),当 \(n=10^9\) 时肯定会爆
-
二分法 \(O(n)=log_2(n)\times n\) ,
当 \(n=10^9\) 时计算结果约是 \(31\times10^9\)
所以用二分法 ,再把判断函数复杂度减小一点就不会超时了。
2.二分
如果 \(mid\) 时间内能完成,那么 \(mid+1\) 时间内肯定也能完成,如图:

3.判断函数
用贪心算法:要让时间最值,就要让人少走路,多搬箱子。
所以让每一个人搬用全力搬走尽可能多的末尾的箱子,还有体力则继续往前推。
代码如下:
bool check(long long time){
int last=n;
for(int i=1;i<=n;i++)b[i]=a[i];
for(int i=1;i<=m;i++){
long long tl=time;
tl-=last;//跑到最后
while(b[last]<=tl){
tl-=b[last];
last--;
if(last==0)return 1;
}//取箱子
b[last]-=tl;//补取
}
return 0;
}
4.你们想要的完整代码:
#include<bits/stdc++.h>
using namespace std;
int n,m,a[100005],b[100005];
bool check(long long time){
int last=n;
for(int i=1;i<=n;i++)b[i]=a[i];
for(int i=1;i<=m;i++){
long long tl=time;
tl-=last;//跑到最后
while(b[last]<=tl){
tl-=b[last];
last--;
if(last==0)return 1;
}//取箱子
b[last]-=tl;//补取
}
return 0;
}//判断函数
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++)cin>>a[i];
while(a[n]==0&&n!=0)n--;//去空末尾
if(n==0){//特判(防止卡常)
cout<<0;
return 0;
}
long long l=0,r=1000000000000000;//两个边界
while(l+1<r){
long long mid=(l+r)>>1;
if(check(mid))r=mid;
else l=mid;
}//二分
cout<<r;
return 0;
}

浙公网安备 33010602011771号