Mono Stack + BS + Seg Tree | 97%
java\nclass Solution {\n    public int[] maximumSumQueries(int[] nums1, int[] nums2, int[][] queries) {\n        // apply filtering here\n        int n = nums1.
```java\nclass Solution {\n    public int[] maximumSumQueries(int[] nums1, int[] nums2, int[][] queries) {\n        // apply filtering here\n        int n = nums1.length;\n        int[][] unfiltered = new int[n][2];\n        \n        for(int i = 0; i < n; i++)\n            unfiltered[i] = new int[]{nums1[i], nums2[i]};\n        \n        Arrays.sort(unfiltered, (a1, a2) -> a1[0] - a2[0]);\n        \n        // Monotonic stack\n\t\t// This will filter the list such that y is decreasing and gets rid of redundant points\n        Deque<Integer> stack = new ArrayDeque<>();\n        for (int i = 0; i < n; i++) {\n            int curr = unfiltered[i][1];\n            while (!stack.isEmpty() && unfiltered[stack.peek()][1] <= curr) {\n                stack.pop();\n            }\n            stack.push(i);\n        }\n        \n        int[][] points = new int[stack.size()][2];\n        \n        // copy over elems from stack to array\n        for (int i = 0; i < points.length; i++) \n            points[i] = unfiltered[stack.pollLast()];\n        \n        int[] ans = new int[queries.length];\n        \n        // create max segment tree\n        SegmentTree tree = new SegmentTree(points);\n        \n        for (int i = 0; i < ans.length; i++) {\n            int xi = queries[i][0];\n            int yi = queries[i][1];\n            // binary search to find the range of qualifying points\n            int xind = BSX(xi, points); \n            int yind = BSY(yi, points);\n            if (points[xind][0] < xi || points[yind][1] < yi) {\n                ans[i] = -1;\n                continue;\n            }\n            \n            // use the segment tree here to find the max point between [xind, yind]\n            ans[i] = tree.query(xind, yind);            \n            \n        }\n        return ans;\n    }\n    \n    \n    public int BSX(int target, int[][] points) {\n        int l = 0, r = points.length - 1;\n        \n        while (l < r) {\n            int mid = (l + r) / 2;\n            int val = points[mid][0]; \n            if (val >= target) {\n                r = mid - 1;\n            } else {\n                l = mid + 1;\n            }\n        }\n        if (l < points.length - 1 && points[l][0] < target) l++;\n        return l;\n    }\n    \n    public int BSY(int target, int[][] points) {\n        int l = 0, r = points.length - 1;\n        \n        while (l < r) {\n            int mid = (l + r) / 2;\n            int val = points[mid][1];\n            if (val >= target) {\n                l = mid + 1;\n            } else {\n                r = mid - 1;\n            }\n        }\n        if (l > 0 && points[l][1] < target) l--;\n        return l;\n    }\n    \n    // Segment Tree for Max Operation\n    class SegmentTree {\n        int n;\n        int[] tree;\n        \n        public SegmentTree(int[][] nums) {\n            n = nums.length;\n            tree = new int[4 * n];\n            build(0, 0, n-1, nums);\n        }\n        \n        public void build(int node, int L, int R, int[][] nums) {\n            if (L == R) {\n                int[] point = nums[L];\n                tree[node] = point[0] + point[1];\n                return;\n            }\n            \n            int M = (L + R)/2;\n            build(node * 2 + 1, L, M, nums);\n            build(node * 2 + 2, M + 1, R, nums);\n            \n            tree[node] = Math.max(tree[node * 2 + 1], tree[node * 2 + 2]);\n        }\n        \n        public int query(int S, int E) {\n            return query(0, 0, n-1, S, E);\n        }\n        \n        public int query(int node, int L, int R, int S, int E) {\n            if (L > E || R < S) return -1;\n            if (L >= S && R <= E) return tree[node];\n            int M = (L + R)/2;\n            return Math.max(query(node * 2 + 1, L, M, S, E), query(node * 2 + 2, M + 1, R, S, E));\n        }\n    }\n}\n```
[]