[ABC294F] Sugar Water 2 题解

可能更好的阅读体验

题目传送门

题目大意

高桥君有 N 瓶糖水,第 i 瓶有 Ai 克糖和 Bi 克水。青木君有 M 瓶糖水,第 i 瓶有 Ci 克糖和 Di 克水。然后两人各拿出一瓶混在一起,求可能产生的第 K 大的浓度百分比是多少,误差在 109 内均为正确。
定义一瓶 x 克糖 y 克水的糖水浓度为 100xx+y%
1N,M51041KNM1Ai,Bi,Ci,Di105,输入均为整数。

题目解析

考虑直接求第 K 大不好算,所以考虑二分答案,然后求一个浓度比他大的数量。
考虑两个瓶糖水混合在一起,浓度大于等于 t

Ai+CjAi+Bi+Cj+Djt

考虑化简,将 Ai,BiCj,Dj 分到不等式两边,得到

Ai(Ai+Bi)tCj+(Cj+Dj)t

这样我们可以按照 Cj+(Cj+Dj)t 排序,枚举 i 二分 j 即可做到 Θ(NlogN) 计算。
加上前面二分答案,复杂度就是 Θ(NlogMlogW),其中 W=1012

坑点:

  • long double 防止卡精度
  • K 的范围是 NM=2.5109,需要 long long
int n,m; ll k; ld l,r,mid,p[maxn],q[maxn];
struct JTZ{
ld x,y;
}a[maxn],b[maxn];
#define mg(i,j) ((a[i].x+b[j].x)*1.0/(a[i].x+a[i].y+b[j].x+b[j].y))
ll js(){
int i,le,ri,midd; ll cnt=0;
for(i=1;i<=n;i++) p[i]=a[i].x-(a[i].x+a[i].y)*mid;
for(i=1;i<=m;i++) q[i]=-b[i].x+(b[i].x+b[i].y)*mid;
sort(q+1,q+m+1);
for(i=1;i<=n;i++){
le=0,ri=m+1;
while(le+1<ri){
midd=(le+ri)>>1;
if(q[midd]<p[i]+1e-12) le=midd; else ri=midd;
}
cnt+=le;
} return cnt;
}
int main(){
n=read(); m=read(); k=read(); int i;
for(i=1;i<=n;i++) a[i].x=read(),a[i].y=read();
for(i=1;i<=m;i++) b[i].x=read(),b[i].y=read();
l=0,r=1;
while(l+EPS<=r){
mid=(l+r)/2;
if(js()<k) r=mid; else l=mid;
}
printf("%.10Lf",l*100.0);
return 0;
}
posted @   jiangtaizhe001  阅读(110)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示