Title

CF954E Water Taps 题解

解题思路

其实题目翻译中已经给出一些提示了。

显然,对于式子 i=1nxi×tii=1nxi=T,我们稍加变形就可以得到 i=1nxi×(tiT)=0。考虑在读入的时候,对于每一个 i[1,n],进行操作 titiT,那么这时的式子即转变为 i=1nxi×ti=0

观察可以发现,在有解的条件下,只有三种 ti 的取值可以满足:

  • i[1,n]ti=0
  • i[1,n],一部分 ti>0 剩下的 ti<0
  • i[1,n],一部分 ti>0 ,一部分 ti<0,其余的 ti=0

将这三种情况综合一下,可以发现只需要第三种情况,那么当 ti=0 时,xi×ti=0,即这个水龙头无论出多少水,对式子的成立情况都没有影响。那么,我们可以直接让这些水龙头的出水取最大值 ai,在接下来的步骤中排除这些水龙头即可。

对于剩下的水龙头,我们考虑按照温度从小到大排序后双指针,设当 i=c 时,ti<0ti+1>0,那么,我们令 l=cr=c+1,分别向 1m 移动,其中 mti 不为 0 的水龙头的数量。分以下三种情况考虑:

  • al×tl+ar×tr<0 ,也就是说,如果此时 lr 水龙头均打开到最大值,那么温度将低于 0(减去后的温度),因此,选择将 r 开到最大值,同时调节 l,使得温度恰好为 0。由于 l 仍然存在一些水量进行分配,那么我们将 r 向右移动一位,同时把 l 的剩余的水量 alal((ar×at)tl)
  • al×tl+ar×tr>0 ,也就是说,如果此时 lr 水龙头均打开到最大值,那么温度将高于 0(减去后的温度),因此,选择将 l 开到最大值,同时调节 r,使得温度恰好为 0。由于 r 仍然存在一些水量进行分配,那么我们将 l 向左移动一位,同时把 r 的剩余的水量 arar((al×al)tr)
  • al×tl+ar×tr=0,两个水龙头均开到最大,并同时分别向左、右移动一。

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);
}
posted @   UncleSam_Died  阅读(15)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下
点击右上角即可分享
微信分享提示