【AtCoder】【ARC072F】Dam

Description

有一坐體積爲m的水庫,每天早上會有水流進來,晚上會放水,
每天流進來的水的溫度和體積都可能不同,倆溫度不同的水混合後的溫度爲:t1v1+t2v2v1+v2
假設水的溫度不受其他因數影響,求第x天(x=1~n)中午水的溫度最高多少(水庫第x天的水必須是滿的)。
當然要保證水庫不會水太多爆炸。

Solution

如果每天流入的水的溫度是遞增的,那麼顯然是取最後m體積的水最優,
對於溫度遞增的入水,我們先放在一個隊列中,不急着混合,
如果一個遞增的入水隊列,在放入了第i天的水後,溫度不是遞增的了,那麼怎麼辦?
因爲第i天的水是必須要全部流進水庫的,我們可以把第i天的水和當前隊列尾的水混合,如還不是遞增的,就一直混合隊尾的兩個水,直到滿足溫度遞增的條件,

這個顯然是正確的(想不到,真的想不到)

複雜度:O(n)

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;
}
發佈了366 篇原創文章 · 獲贊 58 · 訪問量 19萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章