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;
}