E. Water Balance--------------------------思维(贪心)难

There are n water tanks in a row, i-th of them contains ai liters of water. The tanks are numbered from 1 to n from left to right.

You can perform the following operation: choose some subsegment [l,r] (1≤l≤r≤n), and redistribute water in tanks l,l+1,…,r evenly. In other words, replace each of al,al+1,…,ar by al+al+1+⋯+arr−l+1. For example, if for volumes [1,3,6,7] you choose l=2,r=3, new volumes of water will be [1,4.5,4.5,7]. You can perform this operation any number of times.

What is the lexicographically smallest sequence of volumes of water that you can achieve?

As a reminder:

A sequence a is lexicographically smaller than a sequence b of the same length if and only if the following holds: in the first (leftmost) position where a and b differ, the sequence a has a smaller element than the corresponding element in b.

Input
The first line contains an integer n (1≤n≤106) — the number of water tanks.

The second line contains n integers a1,a2,…,an (1≤ai≤106) — initial volumes of water in the water tanks, in liters.

Because of large input, reading input as doubles is not recommended.

Output
Print the lexicographically smallest sequence you can get. In the i-th line print the final volume of water in the i-th tank.

Your answer is considered correct if the absolute or relative error of each ai does not exceed 10−9.

Formally, let your answer be a1,a2,…,an, and the jury’s answer be b1,b2,…,bn. Your answer is accepted if and only if |ai−bi|max(1,|bi|)≤10−9 for each i.

Examples
inputCopy

4
7 5 5 7
outputCopy
5.666666667
5.666666667
5.666666667
7.000000000
inputCopy
5
7 8 8 10 12
outputCopy
7.000000000
8.000000000
8.000000000
10.000000000
12.000000000
inputCopy
10
3 9 5 5 1 7 5 3 8 7
outputCopy
3.000000000
5.000000000
5.000000000
5.000000000
5.000000000
5.000000000
5.000000000
5.000000000
7.500000000
7.500000000
Note
In the first sample, you can get the sequence by applying the operation for subsegment [1,3].

In the second sample, you can’t get any lexicographically smaller sequence.

题意:
给定n个数,每次可以选取一段区间[l,r],使得[l,r]之间的数都变成[l,r]区间之和/区间长度。
问最小的字典序。

解析:
假设现在存在两块区域的平均数 第一块平均数为x1,第二块为x2。题目要求是最小的字典序。我们可以贪心选择,如果下一个数是y,且<x2 那么把y加入到第二块区域中,平均数x2就会减,假设把y加入到x2的结果为B2,然后B2要和x1去比较了 如果B2<x1 那么x1这块区域的平均数也要变小

贪心选择小于平均数。加入进来后,去更新一下后面的平均数。

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+1000;
double a[N],st[N],len[N];
int n;
int main()
{
	scanf("%d",&n);
	for(int i=0;i<n;i++) scanf("%lf",&a[i]);
	int p=0;
	for(int i=0;i<n;i++) 
	{
		st[++p]=a[i];len[p]=1;//st[i]保存平均数,len保存st[i]这个平均数有多少个数 
		while(p>1&&st[p]<st[p-1])//更新后面的数
		{
			st[p-1]=(st[p]*len[p]+st[p-1]*len[p-1])/(len[p]+len[p-1]);
			len[p-1]+=len[p];//更新长度,因为又多了一部分进来
			p--;
		}
	}
	for(int i=1;i<=p;i++) //一共p块区域
	{
		for(int j=1;j<=len[i];j++) //每块区域的个数
		printf("%.8lf\n",st[i]);
	}
}
发布了412 篇原创文章 · 获赞 8 · 访问量 8864

猜你喜欢

转载自blog.csdn.net/qq_43690454/article/details/104328192