• bzoj4030【HEOI2015】小L的白日梦


    题意:http://www.lydsy.com/JudgeOnline/problem.php?id=4030

    sol  :orz Yousiki http://www.cnblogs.com/yousiki/p/6490769.html

       orz jiry http://jiruyi910387714.is-programmer.com/posts/90425.html

       有三个结论:

         1、一定存在一个最优解,使得每天不高兴的概率单调递增

            这个结论很显然,考虑对于一组逆序对将其交换,答案更优

         2、一定存在最优解,由排序后的一段前缀+一段后缀构成

            如果把前缀一个点放到中间比原来优,那么把这个点放到后面一定更优(或者一样)

         3、每一种选取的项目有三种可能:选一个,全选,其他,且第三种至多一个

            这个不会证QAQ,Yousiki大佬说随便想想就知道了QAQ

       这样的话就可以假设第三种情况在后缀(前后缀分别做一次),

       线性往后扫前缀,每次向后跳一个块,考虑后缀的期望会怎么更新,再处理一个快+1的情况即可

       可以把一个点拆成三个:1,cnt,1,这样写起了方便一些,不用再特判

       代码莫名其妙数据一大就WA.......完全不知道为什么QAQ,弃疗了,cogs最后一个点还莫名其妙过了....50points

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cmath>
    #define inf 1e18
    #define double long double
    #define int long long
    using namespace std;
    const int Mx=100010;
    struct Node { int c; double p,w; } A[3*Mx],tmp[Mx];
    bool cmp(Node a,Node b) { return a.p>b.p; }
    int n,k,tot,now,sigma;
    double ans,sum;
    void solve()
    {
        sum=0,now=1,sigma=k;
        for(int i=n;i>=1;i--) sum+=(A[i].c-1)*A[i].w+(1-A[i].p)*A[i+1].p,sigma-=A[i].c;
        for(int i=1;i<=n;i++)
        {
            sigma-=A[i].c;
            while(now<=n&&sigma<=0) sum-=(A[now].c-1)*A[now].w+(1-A[now].p)*A[now+1].p,sigma+=A[now++].c;
            if(sigma<=0) break; sum+=(A[i].c-1)*A[i].w+(1-A[i-1].p)*A[i].p;
            ans=min(ans,sum+(sigma-1)*A[now-1].w+(1-A[now-1].p)*A[now].p+(1-A[i].p)*A[now-1].p);
        }
        sigma=k,sum=0;//初始状态
        for(int i=1,mn=min(sigma,A[i].c);i<=n&&mn;i++)
            sigma-=mn,sum+=(mn-1)*A[i].w+(1-A[i-1].p)*A[i].p;
        ans=min(ans,sum);
    }
    signed main()
    {
        int T; scanf("%lld",&T);
        while(T--)
        {
            scanf("%lld%lld",&n,&k);
            for(int i=1,x,y;i<=n;i++)
                scanf("%lld/%lld%lld",&x,&y,&tmp[i].c),tmp[i].p=(double) x/y,tmp[i].w=(1-tmp[i].p)*tmp[i].p;
            sort(tmp+1,tmp+1+n,cmp); tot=0;
            for(int i=1;i<=n;i++)//拆点
            {
                if(tmp[i].c==1) A[++tot]=tmp[i];
                if(tmp[i].c>1) A[++tot]=tmp[i],A[tot].c=1,A[++tot]=tmp[i],A[tot].c--;
                if(tmp[i].c>2) A[tot].c--,A[++tot]=tmp[i],A[tot].c=1;
            } n=tot;
            ans=inf,A[0].p=1,A[n+1].p=0;
            solve();
            for(int i=1;i<=(n+1)/2;i++) A[i].p=1-A[i].p,A[n-i+1].p=1-A[n-i+1].p,swap(A[i],A[n-i+1]);
            solve();
            printf("%.6LF
    ",fabs(ans));
        }
    }
  • 相关阅读:
    python3-使用进程方式进行并发请求
    matplotlib--添加图例和注解
    matplotlib修改坐标轴刻度值,刻度个数
    matplotlib(一)
    python-jit(提高代码运行速度)
    pandans处理Excel
    base64编解码实现
    wireshark使用
    python 教程
    linux命令之 top, free,ps
  • 原文地址:https://www.cnblogs.com/xiaoxubi/p/6523985.html
Copyright © 2020-2023  润新知