arc072f Dam

对于第i天,我们要给它腾出位置,为了使温度最高,要删除的时前面温度最低的。

对于一个新加入的温度,如果它比之前的温度都要高。直接加入即可。

如果它不是最高温,我们把它与前一个温度混合,直到混合后的温度是最高温。

原因如下:

对于之后加入的温度,我们要么踢掉一部分之前的混合液t2,把它与当前的温度t1混合,要么把它与t1与之前的混合液t2混合的温度t3混合,再踢掉一部分t3以腾出空间(这样可以得到t1<t2<t3)

那么我们显然选择的是t3(温度更高),所以对于这种情况我们要把它与前面的混合

这个我们只要维护一个单调递增的单调队列来维护温度就行了。

代码

#include<bits/stdc++.h>
using namespace std;
#define N 500010
int st,ed;
struct data
{
	double t,v;
} datas[N],q[N];
data merge(data a,data b)
{
	data c;
	c.v=a.v+b.v;
	c.t=(a.t*a.v+b.t*b.v)/c.v;
	return c;
}
signed main()
{
	int n,l;
	cin>>n>>l;
	for(int i=1; i<=n; i++)
	{
		scanf("%lf%lf",&datas[i].t,&datas[i].v);
	}
	double sum=0,tot=0;
	q[st=ed=1]=datas[1],sum=datas[1].v,tot=datas[1].t*datas[1].v;
	printf("%lf\n",datas[1].t);
	for(int i=2; i<=n; i++)
	{
		q[++ed]=datas[i],tot+=datas[i].v*datas[i].t,sum+=datas[i].v;
		while(ed>st&&sum>l)
		{
			if(sum-q[st].v>=l)
			{
				tot-=q[st].v*q[st].t;
				sum-=q[st].v;
				st++;
			}
			else
			{
				q[st].v-=sum-l;
				tot-=(sum-l)*q[st].t;
				sum-=sum-l;
			}
		}
		while(ed>st)
		{
			if(q[ed].t>=q[ed-1].t) break;
			data d=merge(q[ed],q[ed-1]);
			q[--ed]=d;
		}


		printf("%.10f\n",tot/sum);
	}
}

  

上一篇:803. 区间合并


下一篇:P6560 [SBCOI2020] 时光的流逝