传送门
考虑二分次数最大值,也就是答案。考虑如何check,对于第
i
i
i个物体而言,它在每次中一定至少被分配
⌊
a
[
i
]
x
⌋
\lfloor \frac {a[i]}{x}\rfloor
⌊xa[i]⌋个,同时最终会剩下
a
[
i
]
%
x
a[i]\%x
a[i]%x个物品给我们灵活分配,现在设置一个变量
d
i
v
=
∑
i
=
1
k
⌊
a
[
i
]
x
⌋
div=\sum_{i=1}^k\lfloor \frac {a[i]}{x}\rfloor
div=∑i=1k⌊xa[i]⌋,再设置一个变量
r
e
s
=
∑
i
=
1
k
a
[
i
]
%
x
res=\sum_{i=1}^ka[i]\%x
res=∑i=1ka[i]%x,不过由于限制了第
i
i
i个物体的取值范围在
[
l
[
i
]
,
r
[
i
]
]
[l[i],r[i]]
[l[i],r[i]],因此当
⌊
a
[
i
]
x
⌋
<
l
[
i
]
\lfloor \frac {a[i]}{x}\rfloor<l[i]
⌊xa[i]⌋<l[i]意味着不管怎样都没办法分配下去,这时候return false即可,不过当
⌊
a
[
i
]
x
⌋
>
r
[
i
]
\lfloor \frac {a[i]}{x}\rfloor >r[i]
⌊xa[i]⌋>r[i],我们不能让
d
i
v
+
=
⌊
a
[
i
]
x
⌋
div+=\lfloor \frac{a[i]}x\rfloor
div+=⌊xa[i]⌋,此时我们让
d
i
v
div
div加上
r
[
i
]
r[i]
r[i]即可,同时注意此时该物品没有可以灵活分配的余项了,也就是
r
e
s
+
=
0
res+=0
res+=0。
最终求出来的
d
i
v
div
div代表除去灵活分配的
r
e
s
res
res那一部分外,每次所有物品能够分配的最大数目之和,这些数目如果小于
L
L
L,别急着return false,我们还要考虑可以灵活分配的
r
e
s
res
res,我们将它除以
x
x
x,也就是
⌊
r
e
s
x
⌋
\lfloor \frac {res}x\rfloor
⌊xres⌋,这一项代表着每一次中我们都还可以选择
⌊
r
e
s
x
⌋
\lfloor \frac {res}x\rfloor
⌊xres⌋个物品让它们的分配名额
+
1
+1
+1,这也是我们最大化物品数目之和的措施,不过剩下的
r
e
s
%
x
res\%x
res%x就没有任何作用了,因为它不能给
x
x
x次的物品分配都产生贡献。
因此在 x x x次的条件下,我们能够做到最大化的物品数量之和为 d i v + ⌊ r e s x ⌋ div+\lfloor\frac{res}x\rfloor div+⌊xres⌋。如果这个数仍然小于 L L L,就return false,否则return true,注意本题题目中并不要求用完所有的物品。
然后一开始我们需要做一个特判,如果满足 ∑ i l [ i ] > R \sum_il[i]>R ∑il[i]>R或 ∑ i r [ i ] < L \sum_{i}r[i]<L ∑ir[i]<L直接输出0即可。
这列给出一份参考代码:
int k,L,R;
int a[maxn],mi[maxn],mx[maxn];
bool check(ll x){
ll res=0,div=0,cur=0,cre;
if(!x)return true;
FOR(i,0,k){
cur=a[i]/x,cre=a[i]%x;
if(cur<mi[i])return false;
if(cur>mx[i])cur=mx[i],cre=0;
res+=cre;
div+=cur;
}
return div+res/x>=L;
}
int main(){
k=rd(),L=rd(),R=rd();
FOR(i,0,k)a[i]=rd();
ll sm1=0,sm2=0;
FOR(i,0,k)mi[i]=rd(),mx[i]=rd(),sm1+=mi[i],sm2+=mx[i];
if(sm1>R || sm2<L)return wrn(0),0;
ll l=0,r=1e14,ans=0;
while(l<=r){
ll mid=l+r>>1ll;
if(check(mid)){
l=mid+1;
ans=mid;
}else r=mid-1;
}
wrn(ans);
}