package algorithmbasic.basicsets.class26;
import java.util.Arrays;
import java.util.Stack;
public class AllTimesMinToMax {
public static int max2(int[] arr) {
long[] sumArr = new long[arr.length];
sumArr[0] = arr[0];
for (int i = 1; i < arr.length; i++) {
sumArr[i] = sumArr[i - 1] + arr[i];
}
Stack<Integer> stack = new Stack<>();
long Max = Integer.MIN_VALUE;
for (int i = 0; i < arr.length; i++) {
if (stack.isEmpty() || arr[i] > arr[stack.peek()]) {
stack.push(i);
continue;
}
while (!stack.isEmpty() && arr[i] <= arr[stack.peek()]) {
int j = stack.pop();
int leftBoarder = stack.isEmpty() ? -1 : stack.peek();
int rightBorder = i;
long sum = leftBoarder == -1 ? sumArr[rightBorder - 1] : sumArr[rightBorder - 1] - sumArr[leftBoarder];
Max = Math.max(sum * arr[j], Max);
}
stack.push(i);
}
while(!stack.isEmpty()) {
int j = stack.pop();
int leftBoarder = stack.isEmpty() ? -1 : stack.peek();
int rightBorder = arr.length;
long sum = leftBoarder == -1 ? sumArr[rightBorder - 1] : sumArr[rightBorder - 1] - sumArr[leftBoarder];
Max = Math.max(sum * arr[j], Max);
}
return (int) (Max % 1000000007);
}
public static void main(String[] args) {
int testTime = 20000;
int size = 100;
int max = 100;
System.out.println("Test begin");
for (int i = 0; i < testTime; i++) {
int[] arr = gerenareRandomArray(size, max);
int result1 = max2(arr);
int result2 = max1(arr);
if (result1 != result2) {
System.out.println("OOPS");
System.out.println(Arrays.toString(arr));
break;
}
}
System.out.println("Test end");
}
private static int[] gerenareRandomArray(int size, int max) {
int[] arr = new int[(int) (Math.random() * size) + 1];
for (int i = 0; i < arr.length; i++) {
arr[i] = (int) (Math.random() * max) + 1;
}
return arr;
}
public static int max1(int[] arr) {
int MaxMult = Integer.MIN_VALUE;
for (int i = 0; i < arr.length; i++) {
int min = Integer.MAX_VALUE;
int sum = 0;
for (int j = i; j < arr.length; j++) {
min = Math.min(min, arr[j]);
sum += arr[j];
MaxMult = Math.max(MaxMult, min * sum);
}
}
return MaxMult;
}
}