题目:http://codeforces.com/contest/1300/problem/E
题意:给定n个数
,任意次操作,每次操作可以取任意连续子区间,使其该区间的数都变为区间的平均数。构造出字典序最小的序列。
参考:https://blog.csdn.net/qq_43627087/article/details/104249948
题解:要使字典序最小,则要求从左到右开始,每个数都取最小。对于当前数
,往后取区间,使得平均下来,当前数
最小化,设有多个边界
都能使a[pos]最小化,那么我们只需贪心地取最小的
,从左往右计算,时间复杂度为
,超时。
考虑优化,边读边合并,如果当前区间比前面的区间平均值更大,那么将该区间与前面的区间合并。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=1000010;
int n,x;
struct node{
int num;
double val;
node(){}
node(int _num,double _val){
num=_num,val=_val;
}
}tmp;
node a[maxn];
int main(){
scanf("%d",&n);
int cnt=0;
for(int i=1;i<=n;i++){
scanf("%d",&x);
a[cnt++]=node(1,1.0*x);
while(cnt>1&&a[cnt-1].val*a[cnt-2].num<a[cnt-2].val*a[cnt-1].num){
tmp=node(a[cnt-1].num+a[cnt-2].num,a[cnt-1].val+a[cnt-2].val);
cnt--;a[cnt-1]=tmp;
}
}
double val;
for(int i=0;i<cnt;i++){
x=a[i].num;
val=a[i].val/x;
while(x--){
printf("%.10f\n",val);
}
}
return 0;
}
/*
12
8 10 4 6 6 4 1 2 2 6 9 5
*/