CF954E Water Taps 题解
解题思路
其实题目翻译中已经给出一些提示了。
显然,对于式子
观察可以发现,在有解的条件下,只有三种
, ; ,一部分 剩下的 ; ,一部分 ,一部分 ,其余的 ;
将这三种情况综合一下,可以发现只需要第三种情况,那么当
对于剩下的水龙头,我们考虑按照温度从小到大排序后双指针,设当
,也就是说,如果此时 和 水龙头均打开到最大值,那么温度将低于 (减去后的温度),因此,选择将 开到最大值,同时调节 ,使得温度恰好为 。由于 仍然存在一些水量进行分配,那么我们将 向右移动一位,同时把 的剩余的水量 ; ,也就是说,如果此时 和 水龙头均打开到最大值,那么温度将高于 (减去后的温度),因此,选择将 开到最大值,同时调节 ,使得温度恰好为 。由于 仍然存在一些水量进行分配,那么我们将 向左移动一位,同时把 的剩余的水量 ; ,两个水龙头均开到最大,并同时分别向左、右移动一。
AC 代码
代码进行防抄袭处理,勿直接 copy。
#include<math.h>
#include<time.h>
#include<stdio.h>
#include<algorithm>
#define ll long long
#define N 200005
#define eps 1e-15
int n;double T,t[N],a[N];
struct Tap{
double t;
double a;
}tap[N];int m;
inline bool cmp(Tap A,Tap B){
return A.t<B.t;
}signed main(){
scanf("%d%lf",&n,&T);
for(register int i=1;i<=n;++i)
scanf("%lf",&a[i]);
for(register int i=1;i<=n;++i)
scanf("%lf",&t[i]);
for(register int i=1;i<=n;++i)
t[i]=t[i]-T;
double ans=0.0;
for(register int i=1;i<=n;++i){
if(fabs(t[i])<=eps)
ans+=a[i];
else tap[++m]={t[i],a[i]};
}std::sort(tap+1,tap+m+1,cmp);
int l=1,r=m;
while(tap[l].t+eps<=0) ++l;--l;
while(tap[r].t+eps>=0) --r;++r;
while(l>=1&&r<=m){
double _1=tap[l].a*tap[l].t;
double _2=tap[r].a*tap[r].t;
if(_1+_2+eps<0){
tap[l].a-=-_2/tap[l].t;
ans+=tap[r].a-_2/tap[l].t;
++r;
}else if(_1+_2-eps>0){
tap[r].a-=-_1/tap[r].t;
ans+=tap[l].a-_1/tap[r].t;
--l;
}else{
ans+=tap[l].a;
ans+=tap[r].a;
--l,++r;
}
}printf("%12.lf",ans);
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下