Description
有一坐體積爲m的水庫,每天早上會有水流進來,晚上會放水,
每天流進來的水的溫度和體積都可能不同,倆溫度不同的水混合後的溫度爲: ,
假設水的溫度不受其他因數影響,求第x天(x=1~n)中午水的溫度最高多少(水庫第x天的水必須是滿的)。
當然要保證水庫不會水太多爆炸。
Solution
如果每天流入的水的溫度是遞增的,那麼顯然是取最後m體積的水最優,
對於溫度遞增的入水,我們先放在一個隊列中,不急着混合,
如果一個遞增的入水隊列,在放入了第i天的水後,溫度不是遞增的了,那麼怎麼辦?
因爲第i天的水是必須要全部流進水庫的,我們可以把第i天的水和當前隊列尾的水混合,如還不是遞增的,就一直混合隊尾的兩個水,直到滿足溫度遞增的條件,
這個顯然是正確的(想不到,真的想不到)
複雜度:
Code
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fod(i,a,b) for(int i=a;i>=b;i--)
#define JS(q,w) ((d[q][0]*d[q][1]+d[w][0]*d[w][1])/(d[q][0]+d[w][0]))
#define SM(q) (d[q][0]*d[q][1])
using namespace std;
typedef double db;
const int N=500500;
int read(int &n)
{
char ch=' ';int q=0,w=1;
for(;(ch!='-')&&((ch<'0')||(ch>'9'));ch=getchar());
if(ch=='-')w=-1,ch=getchar();
for(;ch>='0' && ch<='9';ch=getchar())q=q*10+ch-48;n=q*w;return n;
}
int m,n;
db ans;
db d[N][2];//v t
int main()
{
int q,w;
read(n),read(m);
int l=1,r=0,all=0;
fo(i,1,n)
{
read(q),read(w);
d[++r][0]=w,d[r][1]=q;ans+=SM(r);
all+=w;
for(;l<r&&d[r-1][1]>=d[r][1];--r)
if(d[r-1][0]+d[r][0]<=m)
{
ans-=SM(r)+SM(r-1);
d[r-1][1]=JS(r-1,r),d[r-1][0]+=d[r][0];
ans+=SM(r-1);
}
else
{
l=--r;
d[r][0]=m-d[r+1][0];
d[r][1]=JS(r,r+1);
d[r][0]=m;all=m;
ans=SM(r);
break;
}
for(;all>m;++l)if(all-d[l][0]>=m)ans-=SM(l),all-=d[l][0];
else
{
ans-=SM(l);
d[l][0]-=(all-m);
ans+=SM(l);all=m;
break;
}
printf("%.10lf\n",ans/m);
}
return 0;
}