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;
}
posted @ 2023-01-10 11:05  ccrui  阅读(23)  评论(0)    收藏  举报