小x的序列
Description
众嗦粥汁,小x比较喜欢的数据结构,平衡树、点分治、lct、二次离线都随便敲,wf的金牌数据结构也不在话下。
今天小y问了小x一个题,大意是这样的,有一个长度为n的数组a,每次可以选择一段连续区间,让后将这段区间内每个数都变成这段区间和的平均数,这个操作可以进行无数次,比如现在有一个数组[1,2,3,4][1,2,3,4][1,2,3,4],你可以选择[1,3][1,3][1,3]这段区间,让后将其变成[2,2,2,4][2,2,2,4][2,2,2,4],现在让你求通过若干次操作后,能得到的字典序最小的数组aaa。
小x表示这个题太简单了,两行就写完了,懒得写,扔给了聪明的你,请你帮他解决这个问题。
所谓字典序最小的数组就是存在两个数组a,ba,ba,b,其中存在一个位置iii,对于pos<ipos<ipos<i,apos=bposa_{pos}=b_{pos}apos=bpos,对于iii,ai<bia_i<b_iai<bi,这个时候我们认为aaa的字典序小于bbb。
Input
输入第一行包含一个整数nnn代表序列aaa的长度,第二行包含nnn个整数表示aaa数组。
保证1≤n,a≤1e61\le n,a\le 1e61≤n,a≤1e6
Output
输出一行包含nnn个元素,代表字典序最小的结果,保留444位小数。
Sample Input 1
4
7 5 5 7
Sample Output 1
5.6667
5.6667
5.6667
7.0000
Sample Input 2
5
7 8 8 10 12
Sample Output 2
7.0000
8.0000
8.0000
10.0000
12.0000
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
#include<cstring>
using namespace std;
const int N =1e6+7;
double a[N],stack[N],jilu[N];
//stack代表有多少个块! 一定是单调增加栈,为了保证最优解! JILU和stack对应!
//贪心解决,仔细观察这一个数字和上一个数字(块)之间的关系,就可以决定这一个数字要不要上去扶贫,
int main()
{
int t,x=0 ;//每个测评机对于初始化的值都不一样!所以初始化0
cin>>t ;
for(int i=1 ;i<=t;i++)//构造一个单增数列!
//观察块之间的关系,进行统一!尽量排除特异,找共性
{
scanf("%lf",&a[i]);
//新加入的这个数字一定会融入绘着她自己就变成最后一个块
//以块为一个单位进行实际操作
stack[++x]=a[i];
jilu[x]=1;
while((stack[x]<stack[x-1])&&x>1)//单调栈进行
//每一个变量都对应实际意义!
{
stack[x-1]=(stack[x-1]*jilu[x-1]+stack[x]*jilu[x])/(jilu[x]+jilu[x-1]);
jilu[x-1]+=jilu[x];
x--;//这一个块依附于上一个块.
}
}
for(int i=1 ;i<=x ;i++)
{
for(int j =1;j<=jilu[i];j++)
printf("%.4lf\n",stack[i]);
}
return 0 ;
}