Codeforces Round #618 (Div. 2)(E. Water Balance)(分块)
time limit per test3 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard output
judge: 点我跳转
Description
There are n n n water tanks in a row, i i i-th of them contains a i a_i ai liters of water. The tanks are numbered from 1 1 1 to n n n from left to right.
You can perform the following operation: choose some subsegment [ l , r ] ( 1 ≤ l ≤ r ≤ n ) [l,r] (1≤l≤r≤n) [l,r](1≤l≤r≤n), and redistribute water in tanks l , l + 1 , … , r l,l+1,…,r l,l+1,…,r evenly. In other words, replace each of a l , a l + 1 , … , a r a_l,a_{l+1},…,a_r al,al+1,…,ar by a l + a l + 1 + ⋯ + a r r − l + 1 \frac{a_l+a_{l+1}+⋯+a_r}{r−l+1} r−l+1al+al+1+⋯+ar. For example, if for volumes [ 1 , 3 , 6 , 7 ] [1,3,6,7] [1,3,6,7] you choose l = 2 , r = 3 l=2,r=3 l=2,r=3, new volumes of water will be [ 1 , 4.5 , 4.5 , 7 ] [1,4.5,4.5,7] [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 a a is lexicographically smaller than a sequence b b b of the same length if and only if the following holds: in the first (leftmost) position where a a a and b b b differ, the sequence a has a smaller element than the corresponding element in b b b.
Input
The first line contains an integer n ( 1 ≤ n ≤ 1 0 6 ) n (1≤n≤10^6) n(1≤n≤106) — the number of water tanks.
The second line contains n integers a 1 , a 2 , … , a n ( 1 ≤ a i ≤ 1 0 6 ) a_1,a_2,…,a_n (1≤a_i≤10^6) 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 i i-th tank.
Your answer is considered correct if the absolute or relative error of each ai does not exceed 1 0 − 9 10^{−9} 10−9.
Formally, let your answer be a 1 , a 2 , … , a n a_1,a_2,…,a_n a1,a2,…,an, and the jury’s answer be b 1 , b 2 , … , b n b_1,b_2,…,b_n b1,b2,…,bn. Your answer is accepted if and only if ∣ a i − b i ∣ m a x ( 1 , ∣ b i ∣ ) ≤ 1 0 − 9 \frac{|a_i−b_i|}{max(1,|b_i|)}≤10^{−9} max(1,∣bi∣)∣ai−bi∣≤10−9 for each i i i.
Examples
input
4
7 5 5 7
output
5.666666667
5.666666667
5.666666667
7.000000000
input
5
7 8 8 10 12
output
7.000000000
8.000000000
8.000000000
10.000000000
12.000000000
input
10
3 9 5 5 1 7 5 3 8 7
output
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 ] [1,3] [1,3].
In the second sample, you can’t get any lexicographically smaller sequence.
题解
暴力肯定过不了。
一个比较巧妙的方法是把区间问题转化成“块”的问题,然后贪心地求解。
每次取数组中的一个元素放到一个新的“块”中,然后比较这个块和前一个块的大小(即当前块的平均值),如果比前一个小,那么说明把当前块和前一个块合并后平均值是变小的,然后再把合并后的块与现在的前一个块进行比较,以此类推,直到当前块的值不比前一个块的值小。
找到最后块的排列即是答案。
代码
#include <bits/stdc++.h>
#define m_p make_pair
#define maxn 1000005
#define _for(i, a) for(int i = 0; i < (a); ++i)
using namespace std;
template<class T>inline void rd(T &res) {
char c; T flag = 1;
while ((c = getchar()) < '0' || c > '9') if (c == '-') flag = -1; res = c - '0';
while ((c = getchar()) >= '0'&&c <= '9') res = res * 10 + c - '0'; res *= flag;
}
int n, a[maxn];
vector< pair< double, int > > bl;
void init() {
bl.clear();
}
void sol() {
init();
_for(i, n) {
bl.push_back(m_p(a[i], 1));
while (bl.size() > 1) {
pair< double, int > &t = bl[bl.size() - 2], ne = bl.back();
if (t.first <= ne.first) break;
t = m_p((t.first * t.second + ne.first * ne.second) / (t.second + ne.second), t.second + ne.second);
bl.pop_back();
}
}
_for(i, bl.size()) {
_for(j, bl[i].second) {
printf("%.9f\n", bl[i].first);
}
}
cout << "\n\n";
}
int main() {
//ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
//freopen("in.txt", "r", stdin);
while (cin >> n) {
_for(i, n) rd(a[i]);
sol();
}
return 0;
}