ARC072_F Dam

题面:

题意:
有一个容量为L的水库,每天晚上可以放任意体积的水。每天早上会有一定温度和体积的水流入水库,要保证流入水之后水的总体积不能超过L。初始水库为空,第一天水流值为L,问每一天水库满容量时的水温最大值。
题解:
①根据题面的表述,每一天不需要在前一天的基础上进行操作,可以从第一天开始独立规划。
②可以写一个具有单调性质的数据结构对于每一天的数据进行存储。
③在维护数据结构时:
·如果第r天水温比第r-1天低,假如要放水,则把第r天和第r-1天的水混合后放会比先放掉第r-1天的水再放第r天的水更优。
这是因为我们可以将高水温的第r-1天看成糖水,r看成清水,联想一下是先糖水清水混合甜还是先把糖水倒掉一部分,再和清水混合甜?
·如果第r天水温比第r-1天高,假如要放水,则选择在第r天前温度最低的水,直接倒掉溢出值,如果溢出值>最低的水的总数,则倒温度次低的水,此操作重复至水恰好不会溢出。
代码:
#include <iostream>
#include <algorithm>
#include <cstdio>
using namespace std;
typedef long long ll;

double col(double t1, int n1, double t2, int n2) {
    return 1.0* (t2 * n2 + t1 * n1) / (double)(n1 + n2);
}

struct node {
    ll n;
    double t;
    node() {}
    node(ll nn, double tt) { n = nn; t = tt; }
}day[500005], today;

int main(void)
{
    ll n, L;
    cin >> n >> L;
    double degree = 0;
    ll l = 1, r = 0;
    ll pour = 0, water = 0;
    for (int i = 1; i <= n; i++)
    {
        double t; ll v;
        cin >> t >> v;
        while (i > 1 && water + v > L)
        {
            pour = min(water + v - L, day[l].n);
            day[l].n = day[l].n - pour;
            water = water - pour;
            degree = degree - day[l].t * pour;
            if (day[l].n == 0) l++;
        }
        water += v;
        degree += 1ll * t * v;
        today = { v, t };
        day[++r] = today;
        while (day[r].t < day[r - 1].t)
        {
            if (l >= r)break;
            day[r - 1] = { day[r - 1].n + day[r].n ,col(day[r].t, day[r].n, day[r - 1].t, day[r - 1].n) };
            r--;
        }
        printf("%.7f
", degree / L);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/ZJNU-huyh/p/14056615.html