题面:
![](https://img2020.cnblogs.com/blog/1927009/202011/1927009-20201129160318898-359027601.png)
题意:
有一个容量为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; }