题目链接:
https://codeforces.com/contest/1300/problem/E
题意:
给出一排水,每次操作可以使得一个区间的水变成区间水的平均值,这种操作可以执行无数次,求出字典序最小的结果
数据范围:
$1leq a leq 1e10$
$1leq 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("----------- "); } for(int i=1;i<=cnt;i++){ for(int j=1;j<=len[i];j++) printf("%.12f ",ans[i]); } return 0; }