@@ -410,4 +410,142 @@ function maximumSumQueries(nums1: number[], nums2: number[], queries: number[][]
410410
411411<!-- solution:end -->
412412
413+ <!-- solution:start -->
414+
415+ ### Solution 2: Sorting + Monotonic Stack + Binary Search
416+
417+ We process queries in descending order of their corresponding $x$ threshold.
418+ At the same time, we also sort number pairs in descending order of $\textit{nums1}[ i] $.
419+
420+ For each $query_j$, all number pairs satisfying $\textit{nums1}[ i] \geq x_j$ are added to a monotonic stack.
421+
422+ Such a stack runs in ascending order of $\textit{nums2}[ i] $ but descending order
423+ of $\textit{nums1}[ i] + \textit{nums2}[ i] $, ensuring that any candidate with a larger $\textit{nums2}[ i] $
424+ has a smaller $\textit{nums1}[ i] + \textit{nums2}[ i] $ instead, so only effective candidates are kept.
425+
426+ For each $query_j$, binary search locates the first stack entry having
427+ $\textit{nums2}[ i] \geq y_j$. Its corresponding $\textit{nums1}[ i] + \textit{nums2}[ i] $ is the answer.
428+
429+ ### Time & Space Complexity
430+
431+ Here, $n$ is the length of array $nums2$, and $m$ is the length of array $queries$.
432+
433+ - Time complexity: $O((n + m) \times \log n + m \times \log m)$。
434+ - Space complexity: $O(n + m)$。
435+
436+ <!-- tabs:start -->
437+
438+ #### Python3
439+
440+ ``` python
441+ class Solution :
442+ def maximumSumQueries (
443+ self , nums1 : list[int ], nums2 : list[int ], queries : list[list[int ]]
444+ ) -> list[int ]:
445+ max_values = [- 1 ] * len (queries)
446+
447+ queries = [(query[0 ], query[1 ], idx) for idx, query in enumerate (queries)]
448+ # Process queries by descending x threshold and y threshold.
449+ queries.sort(key = lambda x : (- x[0 ], - x[1 ]))
450+
451+ tuples: list[tuple[int , int ]] = [] # Format: (num 1, num 2).
452+ for num_1, num_2 in zip (nums1, nums2):
453+ tuples.append((num_1, num_2))
454+
455+ # Process queries by descending num 1 and num 2.
456+ # Sort by ascending num 1 and num 2 to pop from the back.
457+ tuples.sort(key = lambda x : (x[0 ], x[1 ]))
458+
459+ stack: list[tuple[int , int ]] = [] # Format: (num 2, sum).
460+
461+ for query_1, query_2, query_idx in queries:
462+ while tuples and tuples[- 1 ][0 ] >= query_1: # Tuple's num 1 >= x threshold.
463+ num_1, num_2 = tuples.pop(- 1 )
464+ nums_sum = num_1 + num_2
465+
466+ while stack and stack[- 1 ][0 ] < num_2 and stack[- 1 ][1 ] <= nums_sum:
467+ stack.pop(- 1 ) # Stack top isn't better than popped tuple.
468+
469+ insertion_idx = bisect_left(stack, (num_2, nums_sum))
470+
471+ if insertion_idx == len (stack):
472+ stack.insert(insertion_idx, (num_2, nums_sum))
473+
474+ elif stack[insertion_idx][1 ] < nums_sum:
475+ stack.insert(insertion_idx, (num_2, nums_sum))
476+
477+ search_idx = bisect_left(stack, (query_2, 0 ))
478+ if search_idx < len (stack):
479+ max_values[query_idx] = stack[search_idx][1 ]
480+
481+ return max_values
482+ ```
483+
484+ #### C++
485+
486+ ``` cpp
487+ class Solution {
488+ public:
489+ vector<int > maximumSumQueries(vector<int >& nums1, vector<int >& nums2, vector<vector<int >>& queries) {
490+ vector<int > maxValues(queries.size(), -1);
491+
492+ vector<vector<int>> queriesIndices;
493+ for (int idx = 0; idx < queries.size(); idx++)
494+ queriesIndices.push_back({queries[idx][0], queries[idx][1], idx});
495+
496+ // Process queries by descending x threshold and y threshold.
497+ // Sort ascendingly and later pop from the back.
498+ sort(queriesIndices.begin(), queriesIndices.end());
499+
500+ vector<pair<int, int>> numsPairs; // Format: {num 1, num 2}.
501+ for (int idx = 0; idx < nums2.size(); idx++)
502+ numsPairs.push_back({nums1[idx], nums2[idx]});
503+
504+ // Process queries by descending num 1 and num 2.
505+ // Sort by ascending num 1 and num 2 to pop from the back.
506+ sort(numsPairs.begin(), numsPairs.end());
507+
508+ deque<pair<int, int>> stack; // Format: {num 2, sum}.
509+
510+ while (!queriesIndices.empty()) {
511+ int queryOne = queriesIndices.back()[0];
512+ int queryTwo = queriesIndices.back()[1];
513+ int queryIdx = queriesIndices.back()[2];
514+ queriesIndices.pop_back();
515+
516+ // Pair's num 1 >= x threshold.
517+ while (!numsPairs.empty() && numsPairs.back().first >= queryOne) {
518+ auto [numOne, numTwo] = numsPairs.back();
519+ numsPairs.pop_back();
520+ int numsSum = numOne + numTwo;
521+
522+ while (!stack.empty() and stack.back().first < numTwo and stack.back().second <= numsSum)
523+ stack.pop_back(); // Stack top isn't better than popped pair.
524+
525+ pair<int, int> targetPair = {numTwo, numsSum};
526+ int insertion_idx = lower_bound(stack.begin(), stack.end(), targetPair) - stack.begin();
527+
528+ if (insertion_idx == stack.size())
529+ stack.insert(stack.begin() + insertion_idx, targetPair);
530+
531+ else if (stack[insertion_idx].second < numsSum)
532+ stack.insert(stack.begin() + insertion_idx, targetPair);
533+ }
534+
535+ pair<int , int > queryNumTwoPair = {queryTwo, 0};
536+
537+ int search_idx = lower_bound(stack.begin(), stack.end(), queryNumTwoPair) - stack.begin();
538+ if (search_idx < stack.size())
539+ maxValues[queryIdx] = stack[search_idx].second;
540+ }
541+
542+ return maxValues;
543+ }
544+ };
545+ ```
546+
547+ <!-- tabs:end -->
548+
549+ <!-- solution:end -->
550+
413551<!-- problem:end -->
0 commit comments