F Design Problemset 2020小米邀请赛第1场

https://ac.nowcoder.com/acm/contest/7501/F

思想出问题了,这题应该秒的,跟19沈阳那个贪心有点像

二分答案,然后每种题目先把l[i]全部放进每个题集,如果某一种题目不够放就不行,如果每个题集的总数已经大于R了,就直接不行,在L,R中间就直接可以了,不够L就需要贪心地放剩下的

对于每种题目还剩下b[i]种,那么由于每个题集的题目必须在l[i],r[i]之间,由于已经全部放了l[i]个了,不够的最多只能放(r[i]-l[i])*mid,跟b[i]取个min,然后看k种题目平铺过去,能不能够到L

注意mid是可能1e8的,*mid的地方要开__int128

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int maxl=1e5+10;

int k;ll ln,rn,sum;ll ans;
ll a[maxl],l[maxl],r[maxl];
__int128 b[maxl];

inline void prework()
{
	scanf("%d%lld%lld",&k,&ln,&rn);
	sum=0;
	for(int i=1;i<=k;i++)
		scanf("%lld",&a[i]),sum+=a[i];
	for(int i=1;i<=k;i++)
		scanf("%lld%lld",&l[i],&r[i]);
}

inline bool jug(ll mid)
{
	if(mid==0)
		return true;
	ll h=0;
	for(int i=1;i<=k;i++)
	{	
		b[i]=a[i]-(__int128)l[i]*mid;
		h+=l[i];
		if(b[i]<0)
			return false;
	}
	if(h>rn)
		return false;
	if(h>=ln && h<=rn)
		return true;
	h=ln-h;
	ll g=0,lres,res=0;
	for(int i=1;i<=k;i++)
	{
		lres=res;
		if(b[i]>((__int128)r[i]-l[i])*mid)
			b[i]=((__int128)r[i]-l[i])*mid;
		res+=b[i];
		g+=res/mid;res%=mid;
	}
	return g>=h;
	
}

inline void mainwork()
{
	ll lb=0,rb=sum/ln,mid;
	for(int i=1;i<=k;i++)
	if(l[i])
		rb=min(a[i]/l[i],rb);
	while(lb+1<rb)
	{
		mid=(lb+rb)>>1;
		if(jug(mid))
			lb=mid;
		else
			rb=mid;
	}
	if(jug(rb))
		ans=rb;
	else
		ans=rb-1;
}

inline void print()
{
	printf("%lld\n",ans);	
}

int main()
{
	prework();
	mainwork();
	print();
	return 0;
}

猜你喜欢

转载自blog.csdn.net/liufengwei1/article/details/109280634
今日推荐