当青训营遇上码上掘金
第五届青训营需要一定数量的青豆才能拿到结营证书或者大于70青豆还能拿个优秀营员。所以我来参加这个活动来攒青豆了。
这个题目的意思是给定n个长度固定的柱子,计算能得到的青豆的数量最多是多少。这个题和之前做过的一个接雨水的题目可谓是异曲同工,看到这个题目我就知道是那个题的变种。因为得到的青豆的数量是由左右柱子决定的,根据左右柱子的高度,可以得到青豆的数量。
首先,咱们可以把每个每个坐标轴上的点看成是一个容器,然后看每个点上的青豆的多少,根据木桶的短板效应咱们能知道,青豆的数量是容器的最小的柱子所决定的。然后,咱们可以分析一下,每个点的容器会受到左右两边的柱子的影响,对两侧比该点高的点是这样的,根据反证法可以证明一下。
因此,我们可以求一个前缀最大的和后缀最大的数组,然后对每个点进行处理,最后最后每个点能获得的青豆的数量是Max(前缀最大值,后缀最大值)-该点的高度。求前缀最大值数组,某点的前缀最大值数组是该点的前一个点的前缀数组值和该点的高度的最大值。求后缀最大值数组,某点的后缀最大值数组是该点的后一个点的后缀数组值和该点的高度的最大值。最后,把某个点进行遍历一遍,答案即为每个点的前缀最大值数组和后缀最大值数组的最大值-该点的高度值的和。
这个题的最重要的是知道能得到的数量是取决于最短的柱子。
这个题目的实现代码(Java)
import java.util.Scanner;
public class Main {
public static void main(String[] args){
final int N = (int)1e5;
int[] pre_max = new int[N];
int[] suf_max = new int[N];
int[] height = new int[N];
Scanner in = new Scanner(System.in);
int n = in.nextInt();
for(int i = 1; i <= n; i ++){
height[i] = in.nextInt();
}
for(int i = 1; i <= n; i ++){
pre_max[i] = Math.max(pre_max[i-1],height[i]);
}
for(int i = n; i >= 1; i --){
suf_max[i] = Math.max(suf_max[i+1], height[i]);
}
int ans = 0;
for(int i = 1; i <= n; i ++){
ans += Math.min(suf_max[i],pre_max[i])-height[i];
}
System.out.println(ans);
}
}