Skip to content

Commit c29bab0

Browse files
authored
feat: add solutions to lc problem: No.2736 (doocs#1965)
No.2736.Maximum Sum Queries
1 parent 79db69e commit c29bab0

File tree

7 files changed

+863
-37
lines changed

7 files changed

+863
-37
lines changed

solution/2700-2799/2736.Maximum Sum Queries/README.md

+298-1
Original file line numberDiff line numberDiff line change
@@ -59,20 +59,137 @@
5959

6060
<!-- 这里可写通用的实现逻辑 -->
6161

62+
**方法一:树状数组**
63+
64+
本题属于二维偏序问题。
65+
66+
二维偏序是这样一类问题:给定若干个点对 $(a_1, b_1)$, $(a_2, b_2)$, $\cdots$, $(a_n, b_n)$,并定义某种偏序关系,现在给定点 $(a_i, b_i)$,求满足偏序关系的点对 $(a_j, b_j)$ 中的数量/最值。即:
67+
68+
$$
69+
\left(a_{j}, b_{j}\right) \prec\left(a_{i}, b_{i}\right) \stackrel{\text { def }}{=} a_{j} \lesseqgtr a_{i} \text { and } b_{j} \lesseqgtr b_{i}
70+
$$
71+
72+
二维偏序的一般解决方法是排序一维,用数据结构处理第二维(这种数据结构一般是树状数组)。
73+
74+
对于本题,我们可以创建一个数组 $nums$,其中 $nums[i]=(nums_1[i], nums_2[i])$,然后对 $nums$ 按照 $nums_1$ 从大到小的顺序排序,将查询 $queries$ 也按照 $x$ 从大到小的顺序排序。
75+
76+
接下来,遍历每个查询 $queries[i] = (x, y)$,对于当前查询,我们循环将 $nums$ 中所有大于等于 $x$ 的元素的 $nums_2$ 的值插入到树状数组中,树状数组维护的是离散化后的 $nums_2$ 的区间中 $nums_1 + nums_2$ 的最大值。那么我们只需要在树状数组中查询大于等于离散化后的 $y$ 区间对应的最大值即可。注意,由于树状数组维护的是前缀最大值,所以我们在实现上,可以将 $nums_2$ 反序插入到树状数组中。
77+
78+
时间复杂度 $O((n + m) \times \log n + m \times \log m)$,空间复杂度 $O(n + m)$。其中 $n$ 是数组 $nums$ 的长度,而 $m$ 是数组 $queries$ 的长度。
79+
6280
<!-- tabs:start -->
6381

6482
### **Python3**
6583

6684
<!-- 这里可写当前语言的特殊实现逻辑 -->
6785

6886
```python
69-
87+
class BinaryIndexedTree:
88+
__slots__ = ["n", "c"]
89+
90+
def __init__(self, n: int):
91+
self.n = n
92+
self.c = [-1] * (n + 1)
93+
94+
def update(self, x: int, v: int):
95+
while x <= self.n:
96+
self.c[x] = max(self.c[x], v)
97+
x += x & -x
98+
99+
def query(self, x: int) -> int:
100+
mx = -1
101+
while x:
102+
mx = max(mx, self.c[x])
103+
x -= x & -x
104+
return mx
105+
106+
107+
class Solution:
108+
def maximumSumQueries(
109+
self, nums1: List[int], nums2: List[int], queries: List[List[int]]
110+
) -> List[int]:
111+
nums = sorted(zip(nums1, nums2), key=lambda x: -x[0])
112+
nums2.sort()
113+
n, m = len(nums1), len(queries)
114+
ans = [-1] * m
115+
j = 0
116+
tree = BinaryIndexedTree(n)
117+
for i in sorted(range(m), key=lambda i: -queries[i][0]):
118+
x, y = queries[i]
119+
while j < n and nums[j][0] >= x:
120+
k = n - bisect_left(nums2, nums[j][1])
121+
tree.update(k, nums[j][0] + nums[j][1])
122+
j += 1
123+
k = n - bisect_left(nums2, y)
124+
ans[i] = tree.query(k)
125+
return ans
70126
```
71127

72128
### **Java**
73129

74130
<!-- 这里可写当前语言的特殊实现逻辑 -->
75131

132+
```java
133+
class BinaryIndexedTree {
134+
private int n;
135+
private int[] c;
136+
137+
public BinaryIndexedTree(int n) {
138+
this.n = n;
139+
c = new int[n + 1];
140+
Arrays.fill(c, -1);
141+
}
142+
143+
public void update(int x, int v) {
144+
while (x <= n) {
145+
c[x] = Math.max(c[x], v);
146+
x += x & -x;
147+
}
148+
}
149+
150+
public int query(int x) {
151+
int mx = -1;
152+
while (x > 0) {
153+
mx = Math.max(mx, c[x]);
154+
x -= x & -x;
155+
}
156+
return mx;
157+
}
158+
}
159+
160+
class Solution {
161+
public int[] maximumSumQueries(int[] nums1, int[] nums2, int[][] queries) {
162+
int n = nums1.length;
163+
int[][] nums = new int[n][0];
164+
for (int i = 0; i < n; ++i) {
165+
nums[i] = new int[] {nums1[i], nums2[i]};
166+
}
167+
Arrays.sort(nums, (a, b) -> b[0] - a[0]);
168+
Arrays.sort(nums2);
169+
int m = queries.length;
170+
Integer[] idx = new Integer[m];
171+
for (int i = 0; i < m; ++i) {
172+
idx[i] = i;
173+
}
174+
Arrays.sort(idx, (i, j) -> queries[j][0] - queries[i][0]);
175+
int[] ans = new int[m];
176+
int j = 0;
177+
BinaryIndexedTree tree = new BinaryIndexedTree(n);
178+
for (int i : idx) {
179+
int x = queries[i][0], y = queries[i][1];
180+
for (; j < n && nums[j][0] >= x; ++j) {
181+
int k = n - Arrays.binarySearch(nums2, nums[j][1]);
182+
tree.update(k, nums[j][0] + nums[j][1]);
183+
}
184+
int p = Arrays.binarySearch(nums2, y);
185+
int k = p >= 0 ? n - p : n + p + 1;
186+
ans[i] = tree.query(k);
187+
}
188+
return ans;
189+
}
190+
}
191+
```
192+
76193
```java
77194
class Solution {
78195
public int[] maximumSumQueries(int[] nums1, int[] nums2, int[][] q) {
@@ -121,13 +238,193 @@ class Solution {
121238
### **C++**
122239

123240
```cpp
241+
class BinaryIndexedTree {
242+
private:
243+
int n;
244+
vector<int> c;
245+
246+
public:
247+
BinaryIndexedTree(int n) {
248+
this->n = n;
249+
c.resize(n + 1, -1);
250+
}
251+
252+
void update(int x, int v) {
253+
while (x <= n) {
254+
c[x] = max(c[x], v);
255+
x += x & -x;
256+
}
257+
}
124258

259+
int query(int x) {
260+
int mx = -1;
261+
while (x > 0) {
262+
mx = max(mx, c[x]);
263+
x -= x & -x;
264+
}
265+
return mx;
266+
}
267+
};
268+
269+
class Solution {
270+
public:
271+
vector<int> maximumSumQueries(vector<int>& nums1, vector<int>& nums2, vector<vector<int>>& queries) {
272+
vector<pair<int, int>> nums;
273+
int n = nums1.size(), m = queries.size();
274+
for (int i = 0; i < n; ++i) {
275+
nums.emplace_back(-nums1[i], nums2[i]);
276+
}
277+
sort(nums.begin(), nums.end());
278+
sort(nums2.begin(), nums2.end());
279+
vector<int> idx(m);
280+
iota(idx.begin(), idx.end(), 0);
281+
sort(idx.begin(), idx.end(), [&](int i, int j) { return queries[j][0] < queries[i][0]; });
282+
vector<int> ans(m);
283+
int j = 0;
284+
BinaryIndexedTree tree(n);
285+
for (int i : idx) {
286+
int x = queries[i][0], y = queries[i][1];
287+
for (; j < n && -nums[j].first >= x; ++j) {
288+
int k = nums2.end() - lower_bound(nums2.begin(), nums2.end(), nums[j].second);
289+
tree.update(k, -nums[j].first + nums[j].second);
290+
}
291+
int k = nums2.end() - lower_bound(nums2.begin(), nums2.end(), y);
292+
ans[i] = tree.query(k);
293+
}
294+
return ans;
295+
}
296+
};
125297
```
126298
127299
### **Go**
128300
129301
```go
302+
type BinaryIndexedTree struct {
303+
n int
304+
c []int
305+
}
306+
307+
func NewBinaryIndexedTree(n int) BinaryIndexedTree {
308+
c := make([]int, n+1)
309+
for i := range c {
310+
c[i] = -1
311+
}
312+
return BinaryIndexedTree{n: n, c: c}
313+
}
314+
315+
func (bit *BinaryIndexedTree) update(x, v int) {
316+
for x <= bit.n {
317+
bit.c[x] = max(bit.c[x], v)
318+
x += x & -x
319+
}
320+
}
321+
322+
func (bit *BinaryIndexedTree) query(x int) int {
323+
mx := -1
324+
for x > 0 {
325+
mx = max(mx, bit.c[x])
326+
x -= x & -x
327+
}
328+
return mx
329+
}
330+
331+
func maximumSumQueries(nums1 []int, nums2 []int, queries [][]int) []int {
332+
n, m := len(nums1), len(queries)
333+
nums := make([][2]int, n)
334+
for i := range nums {
335+
nums[i] = [2]int{nums1[i], nums2[i]}
336+
}
337+
sort.Slice(nums, func(i, j int) bool { return nums[j][0] < nums[i][0] })
338+
sort.Ints(nums2)
339+
idx := make([]int, m)
340+
for i := range idx {
341+
idx[i] = i
342+
}
343+
sort.Slice(idx, func(i, j int) bool { return queries[idx[j]][0] < queries[idx[i]][0] })
344+
tree := NewBinaryIndexedTree(n)
345+
ans := make([]int, m)
346+
j := 0
347+
for _, i := range idx {
348+
x, y := queries[i][0], queries[i][1]
349+
for ; j < n && nums[j][0] >= x; j++ {
350+
k := n - sort.SearchInts(nums2, nums[j][1])
351+
tree.update(k, nums[j][0]+nums[j][1])
352+
}
353+
k := n - sort.SearchInts(nums2, y)
354+
ans[i] = tree.query(k)
355+
}
356+
return ans
357+
}
358+
```
359+
360+
### **TypeScript**
130361

362+
```ts
363+
class BinaryIndexedTree {
364+
private n: number;
365+
private c: number[];
366+
367+
constructor(n: number) {
368+
this.n = n;
369+
this.c = Array(n + 1).fill(-1);
370+
}
371+
372+
update(x: number, v: number): void {
373+
while (x <= this.n) {
374+
this.c[x] = Math.max(this.c[x], v);
375+
x += x & -x;
376+
}
377+
}
378+
379+
query(x: number): number {
380+
let mx = -1;
381+
while (x > 0) {
382+
mx = Math.max(mx, this.c[x]);
383+
x -= x & -x;
384+
}
385+
return mx;
386+
}
387+
}
388+
389+
function maximumSumQueries(nums1: number[], nums2: number[], queries: number[][]): number[] {
390+
const n = nums1.length;
391+
const m = queries.length;
392+
const nums: [number, number][] = [];
393+
for (let i = 0; i < n; ++i) {
394+
nums.push([nums1[i], nums2[i]]);
395+
}
396+
nums.sort((a, b) => b[0] - a[0]);
397+
nums2.sort((a, b) => a - b);
398+
const idx: number[] = Array(m)
399+
.fill(0)
400+
.map((_, i) => i);
401+
idx.sort((i, j) => queries[j][0] - queries[i][0]);
402+
const ans: number[] = Array(m).fill(0);
403+
let j = 0;
404+
const search = (x: number) => {
405+
let [l, r] = [0, n];
406+
while (l < r) {
407+
const mid = (l + r) >> 1;
408+
if (nums2[mid] >= x) {
409+
r = mid;
410+
} else {
411+
l = mid + 1;
412+
}
413+
}
414+
return l;
415+
};
416+
const tree = new BinaryIndexedTree(n);
417+
for (const i of idx) {
418+
const [x, y] = queries[i];
419+
for (; j < n && nums[j][0] >= x; ++j) {
420+
const k = n - search(nums[j][1]);
421+
tree.update(k, nums[j][0] + nums[j][1]);
422+
}
423+
const k = n - search(y);
424+
ans[i] = tree.query(k);
425+
}
426+
return ans;
427+
}
131428
```
132429

133430
### **...**

0 commit comments

Comments
 (0)