Mr. Kitayuta vs. Bamboos[二分+贪心][图像分析]

文章目录

题目

在这里插入图片描述
在这里插入图片描述

思路

首先最大值最小考虑二分,假设我们检验 x x x
但是发现检验比较难写
尝试从图像分析
那么画出来图像大致如下:
在这里插入图片描述

然后我们发现可以将图像上移末端重合至 ( m , x ) (m,x) (m,x)
在这里插入图片描述

那么只需要倒推改成每天减小 a i a_i ai 高度,每天有 k k k 次机会增加 p p p,保证初始高度大于 h i h_i hi 即可

然后首先可以想到一个类似堆的做法,每次要死了就加,没来得及加的机会存下来
最后调整高度
时间复杂度 O ( m k l o g n l o g A ) O(mklog nlogA) O(mklognlogA)
发现可以更简单在每个必死时间点存储,
倒推要死的时候增加
最后调整高度就可以不用堆
时间复杂度 O ( m k l o g A ) O(mklogA) O(mklogA)

代码

#include<set>
#include<map>
#include<cmath>
#include<queue>
#include<stack>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<iostream>
#include<algorithm>
using namespace std;
#define LL long long
int read(){
	bool f=0;int x=0;char c=getchar();
	while(c<'0'||'9'<c){if(c=='-')f=1;c=getchar();}
	while('0'<=c&&c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
	return !f?x:-x;
}
#define mp make_pair
const int MAXN=100000;
const int INF=0x3f3f3f3f;
typedef pair<int,int> pii;
LL n,m,k,p;
LL h[MAXN+5],a[MAXN+5];
queue<pii> q[MAXN+5];
bool check(LL x){
	for(int i=1;i<=m;i++)
		while(!q[i].empty())
			q[i].pop();
	for(int i=1;i<=n;i++){
		LL s=x/a[i]+1;
		if(s<=m) q[s].push(mp(i,0));
	}
	for(int i=1,c=0;i<=m;i++,c+=k){
		while(!q[i].empty()){
			if(!c) return 0;
			c--;
			pii u=q[i].front();
			q[i].pop(),u.second++;
			LL s=(u.second*p+x)/a[u.first]+1;
			if(s<=m) q[s].push(u);
		}
	}
	LL s=0;
	for(int i=1;i<=n;i++)
		s+=(max(h[i]+a[i]*m-x,0ll)+p-1)/p;
	return s<=m*k;
}
int main(){
	//freopen("bamboo.in","r",stdin);
	//freopen("bamboo.out","w",stdout);
	n=read(),m=read(),k=read(),p=read();
	LL L=0,R=0;
	for(int i=1;i<=n;i++)
		h[i]=read(),a[i]=read(),R=max(R,h[i]+m*a[i]);
	while(L+1<R){
		LL Mid=(L+R)>>1;
		if(check(Mid)) R=Mid;
		else L=Mid;
	}
	printf("%lld\n",R);
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值