topic description
Find the subarray with length at least and maximum geometric mean from an N
array of positive numbers of length , and output its position and size. (The geometric mean of K numbers is the Kth root of the product of K numbers) If there are multiple sub-arrays whose geometric mean is the maximum value, then output the sub-array with the smallest length. If there are multiple subarrays with the same length whose geometric mean is the maximum value, then output the first subarray.numbers
L
enter description
- The first line of input is
N、L
N
Representednumbers
size 1 ≤ N ≤ 100000 1\le N\le 1000001≤N≤100000L
Indicates the minimum length of a subarray 1 ≤ L ≤ N 1\le L\le N1≤L≤N
- The following
N
lines represent the numbernumbers
inN
each line 1 0 − 9 ≤ numbers [ i ] ≤ 1 0 9 10^{-9} \le numbers[i] \le 10^910−9≤numbers[i]≤109
output description
- Output the position (counting from 0) and size of the subarray, separated by a space.
Remark
- The use case guarantees that, except for the subarray whose geometric mean is the maximum value, the geometric mean of the other subarrays is at least 1 smaller than the maximum value 0 − 10 10^{-10}10− Multiples of 10 .
Example
use case 1
- enter
3 2
2
2
3
- output
1 2
- illustrate
- There are 3 sub-arrays with length at least 2, which are
{2, 2}、{2, 3}、{2, 2, 3}
- Among them
{2, 3}
, the geometric mean is the largest, so output its position 1 and length 2
use case 2
- enter
10 2
0.2
0.1
0.2
0.2
0.2
0.1
0.2
0.2
0.2
0.2
- output
2 2
- illustrate
- There are multiple subarrays of length at least 2 that have a geometric mean of 0.2, among which the shortest length is 2, and there are multiple.
- The first subarray of length 2 and geometric mean of 0.2 is a subarray composed of two 0.2 starting from the second number
code display
private static void maxGeoSubArray(double[] numbers, int L) {
// 首先构造前缀积数组
int n = numbers.length;
double[] mul = new double[n+1];
// 初始化第一个元素 为 0
mul[0] = 1.0;
// 填充前缀积数组数据
for(int i = 0;i < n;i++) {
mul[i + 1] = mul[i] * numbers[i];
}
// 初始化左右边界变量
int l = 0,r = 0;
// 保存最大值
double ans = 0.0;
// 双重遍历,去找到 最大几何平均值
for(int i = 0;i <= n - L;i++) {
for(int j = i + L - 1;j < n;j++) {
// 这个时候,计算区间 [i, j] 的几何平均值 j - i + 1
double t = mul[j+1] / mul[i];
int len = j - i + 1;
// 开 len 次方根
double avg = Math.pow(t, 1.0 / len);
// 根据备注要求,几何平均值的大小至少要保证比最大值 小 10^{-10} 次方倍
if(Math.abs(avg - ans) > Math.max(avg, ans) / Math.pow(10, 10) && avg >= ans) {
if(avg == ans) {
int local = r - l + 1;
if(len > local) {
r = j;
l = i;
}
} else {
ans = avg;
r = j;
l = i;
}
}
}
}
// 最终遍历最后然后输出结果 输出 位置 和 长度
System.out.print(l + " ");
System.out.print(r - l + 1);
}