71 lines
1.8 KiB
Java
71 lines
1.8 KiB
Java
|
import java.util.*;
|
||
|
|
||
|
public class AllNearestSmallerValues {
|
||
|
|
||
|
// https://en.wikipedia.org/wiki/All_nearest_smaller_values
|
||
|
public static int[] nsv(int[] a) {
|
||
|
int n = a.length;
|
||
|
int[] p = new int[n];
|
||
|
for (int i = 0; i < n; i++) {
|
||
|
int j = i - 1;
|
||
|
while (j != -1 && a[j] >= a[i]) {
|
||
|
j = p[j];
|
||
|
}
|
||
|
p[i] = j;
|
||
|
}
|
||
|
return p;
|
||
|
}
|
||
|
|
||
|
public static long maxInscribedRectangle(int[] heights) {
|
||
|
int n = heights.length;
|
||
|
int[] rheights = new int[n];
|
||
|
for (int i = 0; i < n; i++) {
|
||
|
rheights[i] = heights[n - 1 - i];
|
||
|
}
|
||
|
int[] lnsv = nsv(heights);
|
||
|
int[] rnsv = nsv(rheights);
|
||
|
long res = 0;
|
||
|
for (int i = 0; i < n; i++) {
|
||
|
int a = lnsv[i] + 1;
|
||
|
int b = n - 1 - rnsv[n - 1 - i] - 1;
|
||
|
long cur = (long) (b - a + 1) * heights[i];
|
||
|
res = Math.max(res, cur);
|
||
|
}
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
public static long maxInscribedRectangle2(int[] heights) {
|
||
|
long res = 0;
|
||
|
Stack<Integer> spos = new Stack<>();
|
||
|
Stack<Integer> sh = new Stack<>();
|
||
|
sh.push(0);
|
||
|
for (int i = 0; i <= heights.length; i++) {
|
||
|
int h = i < heights.length ? heights[i] : 0;
|
||
|
int pos = i;
|
||
|
while (sh.peek() > h) {
|
||
|
pos = spos.pop();
|
||
|
res = Math.max(res, (long) sh.pop() * (i - pos));
|
||
|
}
|
||
|
spos.push(pos);
|
||
|
sh.push(h);
|
||
|
}
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
// Usage example
|
||
|
public static void main(String[] args) {
|
||
|
System.out.println(maxInscribedRectangle(new int[]{1, 2, 3}));
|
||
|
System.out.println(maxInscribedRectangle2(new int[]{1, 2, 3}));
|
||
|
System.out.println(Arrays.toString(nsv(new int[]{1, 1, 3, 2})));
|
||
|
Random rnd = new Random(1);
|
||
|
for (int step = 0; step < 1000; step++) {
|
||
|
int n = rnd.nextInt(10) + 1;
|
||
|
int[] h = rnd.ints(n, 0, 10).toArray();
|
||
|
long res1 = maxInscribedRectangle(h);
|
||
|
long res2 = maxInscribedRectangle2(h);
|
||
|
if (res1 != res2)
|
||
|
throw new RuntimeException();
|
||
|
}
|
||
|
}
|
||
|
}
|