V-Diagram
#贪心 #枚举
题目描述
A 1 1 1-indexed integer sequence a a a of length n n n is a V-diagram if n ≥ 3 n \ge 3 n≥3 and there exists an index i i i ( 1 ≤ i ≤ n 1 \leq i \leq n 1≤i≤n) satisfying the following:
- a j ≥ a j + 1 a_j \geq a_{j + 1} aj≥aj+1 for 1 ≤ j ≤ i 1 \leq j \leq i 1≤j≤i;
- a j ≥ a j − 1 a_j \geq a_{j - 1} aj≥aj−1 for i ≤ j ≤ n i \leq j \leq n i≤j≤n.
Given a V-diagram a a a, find a V-diagram b b b with the maximum possible average such that b b b is a consecutive subsequence of a a a.
A consecutive subsequence of a sequence can be obtained by removing some (possibly zero) elements from the beginning and end of the sequence.
输入格式
Each test contains multiple test cases. The first line contains a single integer t t t ( 1 ≤ t ≤ 1 0 5 1 \le t \le 10^5 1≤t≤105) denoting the number of test cases. For each test case:
The first line contains one integer n n n ( 3 ≤ n ≤ 3 ⋅ 1 0 5 3 \le n \le 3 \cdot 10^5 3≤n≤3⋅105) denoting the length of the integer sequence a a a.
The second line contains n n n integers a 1 , a 2 , … , a n a_1, a_2, \ldots, a_n a1,a2,…,an ( 1 ≤ a i ≤ 1 0 9 1 \le a_i \le 10^9 1≤ai≤109) denoting the sequence a a a itself.
It is guaranteed that a a a is a V-diagram, and the sum of n n n over all test cases does not exceed 3 ⋅ 1 0 5 3 \cdot 10^5 3⋅105.
输出格式
For each test case, output a real number denoting the maximum possible average.
Your answer is considered correct if its absolute or relative error does not exceed 1 0 − 9 10^{-9} 10−9.
Formally, let your answer be x x x, and the jury’s answer be y y y. Your answer will be considered correct if and only if ∣ x − y ∣ max ( 1 , ∣ y ∣ ) ≤ 1 0 − 9 \frac{|x - y|}{\max(1, |y|)} \le 10^{-9} max(1,∣y∣)∣x−y∣≤10−9.
样例 #1
样例输入 #1
2
4
8 2 7 10
6
9 6 5 3 4 8
样例输出 #1
6.75000000000000000000
5.83333333333333303727
解题思路
首先我们满足 V V V形图的前提下(取中间三个数),分别枚举右侧连续取的段数和左边连续取的段数。
具体而言,先枚举右边连续取的段数,如果当前取的大于平均值,则更新平均值,如果不大于,保持右边段取的状态,直到后面大于平均值才更新,然后对左边一段进行同样的操作。
最后,我们今天同样的操作,只不过这次先从左侧开始取,然后才是右侧。
最终答案为二者的最大值。
代码
void solve() {
int n;
cin >> n;
vector<int>a(n + 1);
for (int i = 1; i <= n; ++i) {
cin >> a[i];
}
auto idx = min_element(a.begin() + 1, a.end()) - a.begin();
int s = a[idx] + a[idx - 1] + a[idx+1];
int sum = s, siz = 3, now = 3;
for (int i = idx+2; i <= n; ++i) {
sum += a[i];
siz++;
if (sum * now > s * siz) {
now = siz;
s = sum;
}
}
siz = now, sum = s;
for (int i = idx - 2; i >= 1; --i) {
sum += a[i];
siz++;
if (sum * now > s * siz) {
now = siz;
s = sum;
}
}
double res = (double)s / now;
s = a[idx] + a[idx - 1] + a[idx + 1];
sum = s, siz = 3, now = 3;
for (int i = idx - 2; i >= 1; --i) {
sum += a[i];
siz++;
if (sum * now > s * siz) {
now = siz;
s = sum;
}
}
siz = now, sum = s;
for (int i = idx + 2; i <= n; ++i) {
sum += a[i];
siz++;
if (sum * now > s * siz) {
now = siz;
s = sum;
}
}
res = std::max(res, (double)s / now);
std::cout << fixed << std::setprecision(20) << res<<"\n";
}
signed main() {
ios::sync_with_stdio(0);
std::cin.tie(0);
std::cout.tie(0);
int t = 1;
cin >> t;
while (t--) {
solve();
}
};