codeforces#1300E. Water Balance(贪心)

题目链接:

https://codeforces.com/contest/1300/problem/E

题意:

 给出一排水,每次操作可以使得一个区间的水变成区间水的平均值,这种操作可以执行无数次,求出字典序最小的结果

数据范围:

$1\leq a \leq 1e10$

$1\leq m \leq 1e10$

分析: 

 考虑子问题,如果已经有了前$i$杯水的结果,再加上一杯水应该怎么操作?

 显然最优的方式是,让最后一杯水去和前面的比较,如果最后的水比前面的小,那么就与前面的合并起来

 实现的时候有个巧妙的方法,对于合并好的水我们把他们看作是一个块,这样最多会有$n-1$次合并,保证了复杂度

AC代码:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e6+7;
int n,a[maxn],cnt,len[maxn];
double ans[maxn];
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    for(int i=1;i<=n;i++){
        ans[++cnt]=a[i];
        len[cnt]=1;
        while(cnt>1&&ans[cnt]<ans[cnt-1]){
            ans[cnt-1]=(ans[cnt-1]*len[cnt-1]+ans[cnt]*len[cnt])/(len[cnt]+len[cnt-1]);
            len[cnt-1]+=len[cnt];
            cnt--;
        }
//        printf("-----------\n");
    }
    for(int i=1;i<=cnt;i++){
        for(int j=1;j<=len[i];j++)
            printf("%.12f\n",ans[i]);
    }
    return 0;
}

  

猜你喜欢

转载自www.cnblogs.com/carcar/p/12305440.html