题目大意: 有个水库,最多能存L单位水,一开始是空的,对于n天,每天早上有v[i]单位的,水温为t[i]的水流进来。每天晚上你可以放掉一些水,多少自定。但是必须保证第二天水库不会溢出。现在问,对于每个i,在使用最优放水策略的情况下,第i天水库是满的情况下最高水温(i之间互相独立)。混合后的温度计算就和混合溶液浓度一样计算。 n<=1e5,其他数1e9范围内 。
题解:改用金属的密度、体积和质量来描述。考虑现在要只留下体积L-v的金属,那么多余的金属一定是之前就别加进来。也就是你可以不加之前的金属,但是只要之前的金属没摘干净现在的金属就不能摘出去。因此贪心维护当前金属组成,每次把多余的密度最小的那些摘除去,然后把当前的混和进去。如果当前的密度比加之前的组成里面最大的密度还要大那么就意味着之后可以在不动当前这个得情况下摘除这些东西;否则就一路和并下去,意味着要摘除当前的金属,连带着这些也要摘除。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define N 500010
#define db long double
#define lint long long
#define gc getchar()
using namespace std;
inline int inn()
{
int x,ch;while((ch=gc)<'0'||ch>'9');
x=ch^'0';while((ch=gc)>='0'&&ch<='9')
x=(x<<1)+(x<<3)+(ch^'0');return x;
}
int vs,qv[N],fp,rp;db qr[N],qm[N],ms;
int main()
{
int n=inn(),L=inn();fp=1,rp=0,vs=0,ms=0;
rep(i,1,n)
{
int r=inn(),v=inn(),vr;db m=(db)v*r,mr;
while(fp<=rp&&vs>L-v)
vr=min(vs-(L-v),qv[fp]),
qv[fp]-=vr,vs-=vr,mr=vr*qr[fp],
qm[fp]-=mr,ms-=mr,fp+=(qv[fp]==0);
rp++,vs+=(qv[rp]=v),ms+=(qm[rp]=m),qr[rp]=r;
while(fp<rp&&qr[rp]<=qr[rp-1])
qm[rp-1]+=qm[rp],qv[rp-1]+=qv[rp],
qr[rp-1]=qm[rp-1]/qv[rp-1],rp--;
printf("%.10lf\n",(double)(ms/vs));
}
return 0;
}