P4110 [HEOI2015]小L的白日梦

传送门

题解

//minamoto
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double db;
#define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
char buf[1<<21],*p1=buf,*p2=buf;
int read(){
    int res,f=1;char ch;
    while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1);
    for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0');
    return res*f;
}
const int N=1.5e5+5;
struct node{
    int cnt;db val;
    inline node(){}
    inline node(int x,db y):cnt(x),val(y){}
    inline bool operator <(const node &b)const
    {return val>b.val;}
    inline void in(){
        static int x,y;scanf("%d/%d",&x,&y);
        val=(db)x/y,scanf("%d",&cnt);
    }
}A[N],B[N*3];
int n,m,tot;
inline db calc(){
    db res=1e18,sum=0;ll now=1,rem=m;
    for(int i=n;i;--i)sum+=(B[i].cnt-1)*B[i].val*(1-B[i].val)+(1-B[i].val)*B[i+1].val,rem-=B[i].cnt;
    for(int i=1;i<=n;++i){
        rem-=B[i].cnt;
        while(now<=n&&rem<=0)
        sum-=(B[now].cnt-1)*B[now].val*(1-B[now].val)+(1-B[now].val)*B[now+1].val,rem+=B[now++].cnt;
        if(rem<=0)break;
        sum+=(B[i].cnt-1)*B[i].val*(1-B[i].val)+(1-B[i-1].val)*B[i].val;
        res=min(res,sum+(rem-1)*B[now-1].val*(1-B[now-1].val)+(1-B[now-1].val)*B[now].val+(1-B[i].val)*B[now-1].val);
    }
    rem=m,sum=0;
    for(int i=1;i<=n;++i){
        int mn=min(rem,(ll)B[i].cnt);
        if(!mn)break;rem-=mn,sum+=(mn-1)*B[i].val*(1-B[i].val)+(1-B[i-1].val)*B[i].val;
    }
    return res=min(res,sum);
}
int main(){
//  freopen("testdata.in","r",stdin);
    int T;scanf("%d",&T);
    while(T--){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;++i){
            A[i].in();if(!A[i].cnt)--i,--n;
        }
        sort(A+1,A+1+n),tot=0;
        for(int i=1;i<=n;++i){
            B[++tot]=node(1,A[i].val);
            if(--A[i].cnt){
                if(A[i].cnt>1)B[++tot]=node(A[i].cnt-1,A[i].val);
                B[++tot]=node(1,A[i].val);
            }
        }
        B[0].val=1,B[(n=tot)+1].val=0;
        db ans=calc();
        for(int i=1;i<=(n>>1);++i)swap(B[i],B[n+1-i]);
        for(int i=1;i<=n;++i)B[i].val=1-B[i].val;
        ans=min(ans,calc());
        printf("%.6Lf\n",fabs(ans));
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/bztMinamoto/p/9960841.html