【ICPC】The 2023 ICPC Asia Hangzhou Regional Contest (The 2nd Universal Cup. Stage 22 Hangzhou) M

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 n3 and there exists an index i i i ( 1 ≤ i ≤ n 1 \leq i \leq n 1in) satisfying the following:

  • a j ≥ a j + 1 a_j \geq a_{j + 1} ajaj+1 for 1 ≤ j ≤ i 1 \leq j \leq i 1ji;
  • a j ≥ a j − 1 a_j \geq a_{j - 1} ajaj1 for i ≤ j ≤ n i \leq j \leq n ijn.

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 1t105) 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 3n3105) 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 1ai109) 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 3105.

输出格式

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} 109.

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)xy109.

样例 #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();
	}
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值