import java.util.ArrayList; import java.util.Arrays; import java.util.List; class Solution { private record Query(int height, int index) {} private static List> process(int[] heights, int[][] originalQueries, int[] result) { List> queries = new ArrayList<>(heights.length); for (var i = 0; i < heights.length; ++i) { queries.add(new ArrayList<>()); } for (var i = 0; i < originalQueries.length; ++i) { int a = Math.min(originalQueries[i][0], originalQueries[i][1]); int b = Math.max(originalQueries[i][0], originalQueries[i][1]); if (heights[b] > heights[a] || a == b) { result[i] = b; } else { queries.get(b).add(new Query(heights[a], i)); } } return queries; } private int search(List stack, int height) { int l = 0; int r = stack.size() - 1; var index = -1; while (l <= r) { var mid = (l + r) / 2; if (stack.get(mid).height > height) { index = Math.max(index, mid); l = mid + 1; } else { r = mid - 1; } } return index; } public int[] leftmostBuildingQueries(int[] heights, int[][] originalQueries) { var result = new int[originalQueries.length]; Arrays.fill(result, -1); var queries = process(heights, originalQueries, result); List stack = new ArrayList<>(); for (var i = heights.length - 1; i >= 0; --i) { var size = stack.size(); for (var q : queries.get(i)) { var pos = search(stack, q.height); if (pos < size && pos >= 0) { result[q.index] = stack.get(pos).index; } } while (!stack.isEmpty() && stack.get(stack.size() - 1).height <= heights[i]) { stack.remove(stack.size() - 1); } stack.add(new Query(heights[i], i)); } return result; } }