AT2402 Dam

传送门

考虑到一个很显然的事实:水是逃不掉的,一定要接的
所以我们就可以得到一个结论:如果当前的水温比上次低,就混合起来(因为水是逃不掉的),如果高就保留(因为我可以将前面的全部抛弃,只取这个高的)
维护一个单调递增队列,复杂度\(O(n)\),然后就做完了,答案就在做的过程中统计就好了
代码:

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<queue>
using namespace std;
void read(int &x){
    char ch;bool ok;
    for(ok=0,ch=getchar();!isdigit(ch);ch=getchar())if(ch=='-')ok=1;
    for(x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar());if(ok)x=-x;
}
#define rg register
const int maxn=5e5+10;
int n,m;
double sum,now,a[maxn],b[maxn],ans[maxn];
struct oo{double a,b;}q[maxn];
int main(){
    read(n),read(m);
    for(rg int i=1,x,y;i<=n;i++)read(x),read(y),a[i]=x,b[i]=y;
    int l=1,r=0;ans[1]=a[1];
    for(rg int i=1;i<=n;i++){
        sum=sum+a[i]*b[i],now=now+b[i];
        q[++r]=(oo){a[i],b[i]};
        while(l<=r){
            if(now<=m)break;
            if(now-q[l].b<m){
                sum=sum-q[l].b*q[l].a;
                q[l].b=q[l].b-(now-m);
                sum=sum+q[l].b*q[l].a;
                now=m;
                break;
            }
            else now-=q[l].b,sum-=q[l].b*q[l].a,l++;
        }
        ans[i]=sum/m;
        while(l<r&&q[r].a<q[r-1].a){
            double tot=q[r-1].b+q[r].b;
            sum=sum-q[r].a*q[r].b-q[r-1].a*q[r-1].b,now=now-q[r].b-q[r-1].b;
            q[r-1].a=(q[r].a*q[r].b+q[r-1].a*q[r-1].b)/tot;
            q[r-1].b=tot;
            sum=sum+q[r-1].a*q[r-1].b,now=now+q[r-1].b;
            r--;
        }
    }
    for(rg int i=1;i<=n;i++)printf("%.7lf\n",ans[i]);
}
posted @ 2019-04-18 21:52 蒟蒻--lichenxi 阅读(...) 评论(...) 编辑 收藏