列表

详情


2736. 最大和查询

给你两个长度为 n 、下标从 0 开始的整数数组 nums1nums2 ,另给你一个下标从 1 开始的二维数组 queries ,其中 queries[i] = [xi, yi]

对于第 i 个查询,在所有满足 nums1[j] >= xinums2[j] >= yi 的下标 j (0 <= j < n) 中,找出 nums1[j] + nums2[j]最大值 ,如果不存在满足条件的 j 则返回 -1

返回数组 answer其中 answer[i] 是第 i 个查询的答案。

 

示例 1:

输入:nums1 = [4,3,1,2], nums2 = [2,4,9,5], queries = [[4,1],[1,3],[2,5]]
输出:[6,10,7]
解释:
对于第 1 个查询:xi = 4 且 yi = 1 ,可以选择下标 j = 0 ,此时 nums1[j] >= 4 且 nums2[j] >= 1nums1[j] + nums2[j] 等于 6 ,可以证明 6 是可以获得的最大值。
对于第 2 个查询:xi = 1 且 yi = 3 ,可以选择下标 j = 2 ,此时 nums1[j] >= 1 且 nums2[j] >= 3nums1[j] + nums2[j] 等于 10 ,可以证明 10 是可以获得的最大值。
对于第 3 个查询:xi = 2 且 yi = 5 ,可以选择下标 j = 3 ,此时 nums1[j] >= 2 且 nums2[j] >= 5nums1[j] + nums2[j] 等于 7 ,可以证明 7 是可以获得的最大值。
因此,我们返回 [6,10,7]

示例 2:

输入:nums1 = [3,2,5], nums2 = [2,3,4], queries = [[4,4],[3,2],[1,1]]
输出:[9,9,9]
解释:对于这个示例,我们可以选择下标 j = 2 ,该下标可以满足每个查询的限制。

示例 3:

输入:nums1 = [2,1], nums2 = [2,3], queries = [[3,3]]
输出:[-1]
解释:示例中的查询 xi = 3 且 yi = 3 。对于每个下标 j ,都只满足 nums1[j] < xi 或者 nums2[j] < yi 。因此,不存在答案。 

 

提示:

原站题解

去查看

上次编辑到这里,代码来自缓存 点击恢复默认模板
class Solution { public: vector<int> maximumSumQueries(vector<int>& nums1, vector<int>& nums2, vector<vector<int>>& queries) { } };

rust 解法, 执行用时: 52 ms, 内存消耗: 10.1 MB, 提交时间: 2023-11-17 16:33:25

impl Solution {
    pub fn maximum_sum_queries(nums1: Vec<i32>, nums2: Vec<i32>, queries: Vec<Vec<i32>>) -> Vec<i32> {
        let mut a: Vec<(i32, i32)> = nums1.into_iter().zip(nums2.into_iter()).collect();
        a.sort_by(|x, y| y.0.cmp(&x.0));

        let mut qid: Vec<usize> = (0..queries.len()).collect();
        qid.sort_by(|&i, &j| queries[j][0].cmp(&queries[i][0]));

        let mut ans = vec![-1; queries.len()];
        let mut st: Vec<(i32, i32)> = Vec::new();
        let mut j = 0;
        for &i in &qid {
            let x = queries[i][0];
            let y = queries[i][1];
            while j < a.len() && a[j].0 >= x { // 下面只需关心 a[j].1
                while !st.is_empty() && st.last().unwrap().1 <= a[j].0 + a[j].1 { // a[j].1 >= st.last().unwrap().0
                    st.pop();
                }
                if st.is_empty() || st.last().unwrap().0 < a[j].1 {
                    st.push((a[j].1, a[j].0 + a[j].1));
                }
                j += 1;
            }
            let p = st.partition_point(|&p| p.0 < y);
            if p < st.len() {
                ans[i] = st[p].1;
            }
        }
        ans
    }
}

javascript 解法, 执行用时: 484 ms, 内存消耗: 83.8 MB, 提交时间: 2023-11-17 16:33:07

/**
 * @param {number[]} nums1
 * @param {number[]} nums2
 * @param {number[][]} queries
 * @return {number[]}
 */
var maximumSumQueries = function (nums1, nums2, queries) {
    const a = _.zip(nums1, nums2).sort((a, b) => b[0] - a[0])
    const qid = [...queries.keys()].sort((i, j) => queries[j][0] - queries[i][0]);

    const ans = Array(queries.length);
    const st = [];
    let j = 0;
    for (const i of qid) {
        const [x, y] = queries[i];
        for (; j < a.length && a[j][0] >= x; j++) { // 下面只需关心 a[j][1]
            while (st.length && st[st.length - 1][1] <= a[j][0] + a[j][1]) { // a[j][1] >= st[st.length-1][0]
                st.pop();
            }
            if (!st.length || st[st.length - 1][0] < a[j][1]) {
                st.push([a[j][1], a[j][0] + a[j][1]]);
            }
        }
        const p = lowerBound(st, y);
        ans[i] = p < st.length ? st[p][1] : -1;
    }
    return ans;
};

// 开区间写法,原理请看 b23.tv/AhwfbS2
var lowerBound = function (st, target) {
    let left = -1, right = st.length; // 开区间 (left, right)
    while (left + 1 < right) { // 区间不为空
        const mid = left + ((right - left) >> 1);
        if (st[mid][0] >= target) {
            right = mid; // 范围缩小到 (left, mid)
        } else {
            left = mid; // 范围缩小到 (mid, right)
        }
    }
    return right; // 或者 left+1
}

cpp 解法, 执行用时: 436 ms, 内存消耗: 180.8 MB, 提交时间: 2023-11-17 16:32:41

class Solution {
public:
    vector<int> maximumSumQueries(vector<int> &nums1, vector<int> &nums2, vector<vector<int>> &queries) {
        vector<pair<int, int>> a(nums1.size());
        for (int i = 0; i < nums1.size(); i++) {
            a[i] = {nums1[i], nums2[i]};
        }
        sort(a.begin(), a.end(),
             [](auto &a, auto &b) { return a.first > b.first; });

        vector<int> qid(queries.size());
        iota(qid.begin(), qid.end(), 0);
        sort(qid.begin(), qid.end(),
             [&](int i, int j) { return queries[i][0] > queries[j][0]; });

        vector<int> ans(queries.size());
        vector<pair<int, int>> st;
        int j = 0;
        for (int i: qid) {
            int x = queries[i][0], y = queries[i][1];
            for (; j < a.size() && a[j].first >= x; j++) { // 下面只需关心 a[j].second
                while (!st.empty() && st.back().second <= a[j].first + a[j].second) { // a[j].second >= st.back().first
                    st.pop_back();
                }
                if (st.empty() || st.back().first < a[j].second) {
                    st.emplace_back(a[j].second, a[j].first + a[j].second);
                }
            }
            auto it = lower_bound(st.begin(), st.end(), y,
                          [](const auto &p, int val) { return p.first < val; });
            ans[i] = it != st.end() ? it->second : -1;
        }
        return ans;
    }
};

java 解法, 执行用时: 63 ms, 内存消耗: 85 MB, 提交时间: 2023-11-17 16:32:17

class Solution {
    public int[] maximumSumQueries(int[] nums1, int[] nums2, int[][] queries) {
        int n = nums1.length;
        int[][] a = new int[n][2];
        for (int i = 0; i < n; i++) {
            a[i][0] = nums1[i];
            a[i][1] = nums2[i];
        }
        Arrays.sort(a, (x, y) -> y[0] - x[0]);

        Integer[] qid = new Integer[queries.length];
        for (int i = 0; i < queries.length; i++) {
            qid[i] = i;
        }
        Arrays.sort(qid, (i, j) -> queries[j][0] - queries[i][0]);

        int[] ans = new int[queries.length];
        List<int[]> st = new ArrayList<>();
        int j = 0;
        for (int i : qid) {
            int x = queries[i][0], y = queries[i][1];
            for (; j < n && a[j][0] >= x; j++) { // 下面只需关心 a[j][1]
                while (!st.isEmpty() && st.get(st.size() - 1)[1] <= a[j][0] + a[j][1]) { // a[j][1] >= st.get(st.size()-1)[0]
                    st.remove(st.size() - 1);
                }
                if (st.isEmpty() || st.get(st.size() - 1)[0] < a[j][1]) {
                    st.add(new int[]{a[j][1], a[j][0] + a[j][1]});
                }
            }
            int p = lowerBound(st, y);
            ans[i] = p < st.size() ? st.get(p)[1] : -1;
        }
        return ans;
    }

    // 开区间写法,原理请看 b23.tv/AhwfbS2
    private int lowerBound(List<int[]> st, int target) {
        int left = -1, right = st.size(); // 开区间 (left, right)
        while (left + 1 < right) { // 区间不为空
            int mid = (left + right) >>> 1;
            if (st.get(mid)[0] >= target) {
                right = mid; // 范围缩小到 (left, mid)
            } else {
                left = mid; // 范围缩小到 (mid, right)
            }
        }
        return right;
    }
}

golang 解法, 执行用时: 328 ms, 内存消耗: 21.8 MB, 提交时间: 2023-06-13 14:51:04

func maximumSumQueries(nums1, nums2 []int, queries [][]int) (ans []int) {
	type pair struct{ x, y int }
	a := make([]pair, len(nums1))
	for i, x := range nums1 {
		a[i] = pair{x, nums2[i]}
	}
	sort.Slice(a, func(i, j int) bool { return a[i].x < a[j].x })
	for i := range queries {
		queries[i] = append(queries[i], i)
	}
	sort.Slice(queries, func(i, j int) bool { return queries[i][0] > queries[j][0] })

	ans = make([]int, len(queries))
	st := []pair{}
	i := len(a) - 1
	for _, q := range queries {
		for i >= 0 && a[i].x >= q[0] {
			for len(st) > 0 && st[len(st)-1].y <= a[i].x+a[i].y {
				st = st[:len(st)-1] // a[i].y >= st[len(st)-1].x
			}
			if len(st) == 0 || st[len(st)-1].x < a[i].y {
				st = append(st, pair{a[i].y, a[i].x + a[i].y})
			}
			i--
		}
		j := sort.Search(len(st), func(i int) bool { return st[i].x >= q[1] })
		if j < len(st) {
			ans[q[2]] = st[j].y
		} else {
			ans[q[2]] = -1
		}
	}
	return ans
}

python3 解法, 执行用时: 328 ms, 内存消耗: 65.1 MB, 提交时间: 2023-06-13 14:50:45

# 排序 + 单调栈上二分
class Solution:
    def maximumSumQueries(self, nums1: List[int], nums2: List[int], queries: List[List[int]]) -> List[int]:
        ans = [-1] * len(queries)
        st = []
        a = sorted((a, b) for a, b in zip(nums1, nums2))
        i = len(a) - 1
        for qid, (x, y) in sorted(enumerate(queries), key=lambda p: -p[1][0]):
            while i >= 0 and a[i][0] >= x:
                ax, ay = a[i]
                while st and st[-1][1] <= ax + ay:  # ay >= st[-1][0]
                    st.pop()
                if not st or st[-1][0] < ay:
                    st.append((ay, ax + ay))
                i -= 1
            j = bisect_left(st, (y,))
            if j < len(st):
                ans[qid] = st[j][1]
        return ans

上一题