F Design Problemset(二分)

F Design Problemset

以前从不发有关二分的博客,之所以发这篇,是因为这个二分太有意思了

题意:一共有k种题目,每场比赛每种题目数量要限制在 [ l i , r r ] [l_i,r_r] [li,rr],每场比赛题目总数要在 [ L , R ] [L,R] [L,R],每种题目,有 a i a_i ai道,求最多可以进行多少次比赛

思路考虑二分:

二分比赛场数

判定方式如下:如果每道题目的数量到满足去最小的时候, a i a_i ai大于其和,即 a i > = m i d ∗ l i a_i>=mid*l_i ai>=midli

这个时候还要考虑 L > ∑ l i L>{\sum}l_i L>li,那么把所有剩余的能加的题目加起来看,能不能满足这个条件,即 s u m > = ( L − ∑ l i ) ∗ m i d sum>=(L-{\sum}l_i)*mid sum>=(Lli)mid,其中剩余的且能加数量为 ∑ m i n ( m i d ∗ ( r i − l i ) , a i − m i d ∗ l i ) {\sum}min(mid*(r_i-l_i),a_i-mid*l_i) min(mid(rili),aimidli)

另外需要特判,特判如下 ∑ l i > R {\sum}l_i>R li>R ∑ r i < L {\sum}r_i<L ri<L

的确是很有意思的二分

#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
#include <bits/stdc++.h>
#define inf 0x7fffffff
//#define ll long long
//#define int long long
#define int __int128
//#define double long double
#define re int
#define void inline void
#define eps 1e-8
//#define mod 1e9+7
#define ls(p) p<<1
#define rs(p) p<<1|1
#define pi acos(-1.0)
#define pb push_back
#define P pair < int , int >
#define mk make_pair
using namespace std;
//const int mod=1e9+7;
//const int M=1e8+5;
//const int N=8e5+5;//?????????? 4e8
int k,L,R;
int l[800005],r[800005];
int a[800005];
int suml,sumr;
int ans;
template<typename T> inline T read()
{
	T sum = 0, fg = 1; char c = getchar();
	for (; !isdigit(c); c = getchar()) if (c == '-') fg = -1;
	for (; isdigit(c); c = getchar()) sum = (sum << 3) + (sum << 1) + (c ^ 0x30);
	return fg * sum;
}
void write(int x)
{
	if(x==0)  return;
	write(x/10);
	putchar(x%10+'0');
}
bool check(int mid)
{
	for(re i=1;i<=k;i++)  if(l[i]*mid>a[i])  return 0;
	int cnt=0;
	for(re i=1;i<=k;i++)  cnt+=min(a[i]-mid*l[i],mid*(r[i]-l[i]));
	return cnt>=(L-suml)*mid;
	
}
void solve()
{
//	cin>>k>>L>>R;
	k=read<int>();
	L=read<int>();
	R=read<int>();
	for(re i=1;i<=k;i++)  a[i]=read<int>();
	for(re i=1;i<=k;i++)  l[i]=read<int>(),r[i]=read<int>(),suml+=l[i],sumr+=r[i];
	if(sumr<L||suml>R)
	{
		puts("0");
		return;
	}
//	if(L<=suml&&suml<=R)
//	{
//		ans=1e18;
//		for(re i=1;i<=k;i++)  ans=min(ans,a[i]/l[i]);
//		cout<<ans<<endl;
//		return;
//	}
	int ll=0,rr=1e14;
	while(ll<rr)
	{
		int mid=(ll+rr+1)>>1;
		if(check(mid))  ans=mid,ll=mid;
		else  rr=mid-1;
	}
	write(ll);
//	cout<<ll<<endl;
}
signed main()
{
    int T=1;
//    cin>>T;
    for(int index=1;index<=T;index++)
    {
//    	printf("Case %d:\n",index);
        solve();
//        puts("");
    }
    return 0;
}
/*


3 4
DDDS
WAAS
WAAA




*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值