zoukankan      html  css  js  c++  java
  • [arc072F]Dam-[单调队列]

    Description

    传送门

    Solution

    首先我们肯定不能那么耿直地直接把水混合起来吧。。不然分分钟完球。

    那么怎么找到最优解呢?假如我们把水的体积和温度按顺序插入队列,这时我们插入第i天的水。假如这个时候水量超过了L,我们要把前面的部分水排掉。

    我们目前有两种排水方法:

    1.不断去掉队列的队首(即最开始插入队列的水)

    2.选一个位置j,把队列中位置[1,j]的水量按照比例分别减少一部分(就是在第j个位置对应的当天倒掉一部分水)

    普通的队列,无法比较方法1,2的优劣。我们考虑单调队列(队列中的水的温度保持单调递增)

    由于我们的队列是单调的,显然第1种更优。

    那么,插入了第i天的水后,还要确保队列的单调。设当前队列的队尾下标为r。

    假如说第i天的水温比r的水温低,那么假如要放水,把i和r混合后放显然会比先放掉r的水再放i的水更优。所以我们把i和r混合起来。

    如此直到队列恢复单调。

    Code

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #define _v first
    #define _t second
    using namespace std;
    typedef long long ll;
    pair<ll,double> q[500010];
    int n,L,t,v;
    int l=1,r=0;
    ll pour,all_water=0;double degree=0;
    int main()
    {
        scanf("%d%d",&n,&L);
        for (int i=1;i<=n;i++)
        {
            scanf("%d%d",&t,&v);
            while (all_water+v>L)
            {
                pour=min(q[l]._v,all_water+v-L);
                q[l]._v-=pour;
                all_water-=pour;    
                degree-=q[l]._t*pour;
                if (!q[l]._v) l++;
            }
            all_water+=v;degree+=1ll*t*v;
            q[++r]=make_pair(v,t);
            while (l<r&&q[r]._t<q[r-1]._t)
            {
                q[r-1]._t=(q[r]._t*q[r]._v+q[r-1]._t*q[r-1]._v)/(q[r]._v+q[r-1]._v);
                q[r-1]._v+=q[r]._v;r--;
            }
            printf("%.7f
    ",degree/L);
        }
    }

     

  • 相关阅读:
    Android项目打包
    Video Demystified
    C指针与python bytes 互转
    运筹学笔记 3 线性代数基础
    三角网格上的寻路算法Part.2—A*算法
    三角网格上的寻路算法Part.1—Dijkstra算法
    从二维点集重建平面形状-浅议凹包算法
    二值图像膨胀腐蚀算法的几种实现方式
    浅议像素化与体素化Part.1——平面图形像素化
    寻找图像中的局部极大点
  • 原文地址:https://www.cnblogs.com/coco-night/p/9690787.html
Copyright © 2011-2022 走看看