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 spos = new Stack<>(); Stack 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(); } } }