2021-09-27小x的序列(单调栈+分块)

小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 ; 
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值