版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_32767041/article/details/86440871
Description
牛客网 2018校招真题 选区间
Solving Ideas
n的范围[1,500000]太大,直接dp会超时
因为区间计算值都是由 区间最小值*区间和 得到的,所以在给定区间最小值的情况下,最优的情况一定是这个区间尽可能的扩展,直至区间的最小值不满足给定的最小值。
(扩展的过程因为满足 区间最小值 >= 给定区间最小值 的情况下,区间和一直增大,所以最终结果也增大)
又因为所有的数字都在[0, 100]的范围内,所以只需要遍历每一个数字为区间最小值的情况即可。
例如有序列[11, 12, 13, 1, 20, 21, 2, 30],设i表示给定的区间最小值,当i=10时,即规定 区间最小值 >= 10,
- 满足区间的条件有[11, 12, 13], [20, 21], [30]
- 对应的计算值为 11*(11+12+13), 20*(20+21), 30*30
- 在给定i=10的情况下,最优值为max(11*(11+12+13), 20*(20+21), 30*30)
所以对i所有可能的情况都遍历一遍就能确定最终的最优值,i属于[0, 100]
Solution
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
/**
* n的范围[1,500000]太大,直接dp会超时
*
* 因为区间计算值都是由 区间最小值*区间和 得到的,
* 所以在给定区间最小值的情况下,最优的情况一定是这个区间尽可能的扩展,
* 直至区间的最小值不满足给定的最小值。
* (扩展的过程因为满足 区间最小值 >= 给定区间最小值 的情况下,
* 区间和一直增大,所以最终结果也增大)
*
* 又因为所有的数字都在[0, 100]的范围内,
* 所以只需要遍历每一个数字为区间最小值的情况即可。
*
* 例如有序列[11, 12, 13, 1, 20, 21, 2, 30],设i表示给定的区间最小值
* 当i=10时,即规定 区间最小值 >= 10,
* 满足区间的条件有[11, 12, 13], [20, 21], [30]
* 对应的计算值为 11*(11+12+13), 20*(20+21), 30*30
* 在给定i=10的情况下,最优值为max(11*(11+12+13), 20*(20+21), 30*30)
* 所以对i所有可能的情况都遍历一遍就能确定最终的最优值,i属于[0, 100]
*
* @author wylu
*/
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String str;
while ((str = br.readLine()) != null) {
int n = Integer.parseInt(str);
int[] a = new int[n];
String[] numStrs = br.readLine().split(" ");
for (int i = 0; i < n; i++) {
a[i] = Integer.parseInt(numStrs[i]);
}
long res = 0;
for (int i = 0; i <= 100; i++) {
int realMin = Integer.MAX_VALUE; //真正的区间最小值
long sum = 0;
boolean allBigger = true; //是否全部的a[j]都>=i
for (int j = 0; j < n; j++) {
if (a[j] >= i) {
sum += a[j];
realMin = Math.min(realMin, a[j]);
}else {
allBigger = false;
res = Math.max(res, realMin * sum);
sum = 0;
realMin = Integer.MAX_VALUE;
}
}
if (allBigger) res = Math.max(res, realMin * sum);
}
System.out.println(res);
}
}
}