Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 11e11f8

Browse files
committed
第440场周赛T1~T4 (4)
1 parent 93c7dc1 commit 11e11f8

File tree

8 files changed

+351
-0
lines changed

8 files changed

+351
-0
lines changed
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
public class Solution3477 {
2+
}
3+
/*
4+
3477. 将水果放入篮子 II
5+
https://leetcode.cn/problems/fruits-into-baskets-ii/description/
6+
7+
第 440 场周赛 T1。
8+
9+
给你两个长度为 n 的整数数组,fruits 和 baskets,其中 fruits[i] 表示第 i 种水果的 数量,baskets[j] 表示第 j 个篮子的 容量。
10+
你需要对 fruits 数组从左到右按照以下规则放置水果:
11+
- 每种水果必须放入第一个 容量大于等于 该水果数量的 最左侧可用篮子 中。
12+
- 每个篮子只能装 一种 水果。
13+
- 如果一种水果 无法放入 任何篮子,它将保持 未放置。
14+
返回所有可能分配完成后,剩余未放置的水果种类的数量。
15+
提示:
16+
n == fruits.length == baskets.length
17+
1 <= n <= 100
18+
1 <= fruits[i], baskets[i] <= 1000
19+
20+
同: 3479. 将水果装入篮子 III
21+
https://leetcode.cn/problems/fruits-into-baskets-iii/description/
22+
*/
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import java.util.Arrays;
2+
import java.util.Comparator;
3+
import java.util.PriorityQueue;
4+
5+
public class Solution3478 {
6+
public long[] findMaxSum(int[] nums1, int[] nums2, int k) {
7+
int n = nums1.length;
8+
Integer[] ids = new Integer[n];
9+
for (int i = 0; i < n; i++) ids[i] = i;
10+
Arrays.sort(ids, Comparator.comparingInt(o -> nums1[o]));
11+
12+
long[] ans = new long[n];
13+
int l = 0, r = 0;
14+
PriorityQueue<Integer> pq = new PriorityQueue<>();
15+
long sumK = 0;
16+
while (r < n) {
17+
while (nums1[ids[l]] < nums1[ids[r]]) {
18+
pq.add(nums2[ids[l]]);
19+
sumK += nums2[ids[l]];
20+
if (pq.size() > k) {
21+
Integer top = pq.remove();
22+
sumK -= top;
23+
}
24+
l++;
25+
}
26+
ans[ids[r]] = sumK;
27+
28+
r++;
29+
}
30+
return ans;
31+
}
32+
}
33+
/*
34+
3478. 选出和最大的 K 个元素
35+
https://leetcode.cn/problems/choose-k-elements-with-maximum-sum/description/
36+
37+
第 440 场周赛 T2。
38+
39+
给你两个整数数组,nums1 和 nums2,长度均为 n,以及一个正整数 k 。
40+
对从 0 到 n - 1 每个下标 i ,执行下述操作:
41+
- 出所有满足 nums1[j] 小于 nums1[i] 的下标 j 。
42+
- 这些下标对应的 nums2[j] 中选出 至多 k 个,并 最大化 这些值的总和作为结果。
43+
返回一个长度为 n 的数组 answer ,其中 answer[i] 表示对应下标 i 的结果。
44+
提示:
45+
n == nums1.length == nums2.length
46+
1 <= n <= 10^5
47+
1 <= nums1[i], nums2[i] <= 10^6
48+
1 <= k <= n
49+
50+
离线询问 + 堆维护 topK。
51+
时间复杂度 O(nlogn)。
52+
*/
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
import java.util.Arrays;
2+
3+
public class Solution3479 {
4+
public int numOfUnplacedFruits(int[] fruits, int[] baskets) {
5+
int n = fruits.length;
6+
LazySegmentTree seg = new LazySegmentTree(n);
7+
seg.build(baskets, 1, 0, n - 1);
8+
int ans = 0;
9+
for (int fr : fruits) {
10+
int pos = seg.findFirst(1, 0, n - 1, fr);
11+
if (pos == -1) {
12+
ans++;
13+
} else {
14+
seg.modify(1, 0, n - 1, pos, pos, 0);
15+
}
16+
}
17+
return ans;
18+
}
19+
20+
// 线段树模板,只需要实现 mergeInfo 和 _do,其余都是固定的
21+
static class LazySegmentTree {
22+
static class Info {
23+
int max0; // 区间最长连续 0 的个数
24+
int lazy; // 懒标记
25+
26+
public Info(int max0, int lazy) {
27+
this.max0 = max0;
28+
this.lazy = lazy;
29+
}
30+
}
31+
32+
Info mergeInfo(Info a, Info b, int l, int r) {
33+
int m = (l + r) >> 1;
34+
35+
int max0 = Math.max(a.max0, b.max0);
36+
return new Info(max0, -1);
37+
}
38+
39+
void _do(int p, int l, int r, int qv) {
40+
// int size = qv <= 0 ? r - l + 1 : 0;
41+
// info[p].pre0 = info[p].suf0 = info[p].max0 = size;
42+
info[p].max0 = qv;
43+
info[p].lazy = qv;
44+
}
45+
46+
int n;
47+
Info[] info;
48+
49+
public LazySegmentTree(int n) {
50+
this.n = n;
51+
info = new Info[4 * n];
52+
Arrays.setAll(info, e -> new Info(0, -1));
53+
}
54+
55+
void build(int[] A, int p, int l, int r) {
56+
// _do(p, l, r, -1);
57+
if (l == r) {
58+
info[p] = new Info(A[l], -1);
59+
return;
60+
}
61+
int m = (l + r) >> 1;
62+
build(A, p << 1, l, m);
63+
build(A, p << 1 | 1, m + 1, r);
64+
maintain(p, l, r);
65+
}
66+
67+
void maintain(int p, int l, int r) {
68+
info[p] = mergeInfo(info[p << 1], info[p << 1 | 1], l, r);
69+
}
70+
71+
void spread(int p, int l, int r) {
72+
int v = info[p].lazy;
73+
if (v == -1) return;
74+
int m = (l + r) >> 1;
75+
_do(p << 1, l, m, v);
76+
_do(p << 1 | 1, m + 1, r, v);
77+
info[p].lazy = -1;
78+
}
79+
80+
void modify(int p, int l, int r, int ql, int qr, int qv) {
81+
if (ql <= l && r <= qr) {
82+
_do(p, l, r, qv);
83+
return;
84+
}
85+
spread(p, l, r);
86+
int m = (l + r) >> 1;
87+
if (ql <= m) modify(p << 1, l, m, ql, qr, qv);
88+
if (qr > m) modify(p << 1 | 1, m + 1, r, ql, qr, qv);
89+
maintain(p, l, r);
90+
}
91+
92+
Info query(int p, int l, int r, int ql, int qr) {
93+
if (ql <= l && r <= qr) {
94+
return info[p];
95+
}
96+
spread(p, l, r);
97+
int m = (l + r) >> 1;
98+
if (qr <= m) return query(p << 1, l, m, ql, qr);
99+
if (ql > m) return query(p << 1 | 1, m + 1, r, ql, qr);
100+
return mergeInfo(query(p << 1, l, m, ql, qr), query(p << 1 | 1, m + 1, r, ql, qr), l, r);
101+
}
102+
103+
// 线段树二分,找最左边的区间左端点,满足区间全为 0 且长度 >= size
104+
// 如果不存在这样的区间,返回 -1
105+
public int findFirst(int p, int l, int r, int size) {
106+
if (info[p].max0 < size) {
107+
return -1;
108+
}
109+
if (l == r) {
110+
return l;
111+
}
112+
spread(p, l, r);
113+
int m = (l + r) / 2;
114+
int idx = findFirst(p << 1, l, m, size); // 递归左子树
115+
if (idx == -1) {
116+
// 左子树的后缀 0 个数 + 右子树的前缀 0 个数 >= size
117+
// if (info[p << 1].suf0 + info[p << 1 | 1].pre0 >= size) {
118+
// return m - info[p << 1].suf0 + 1;
119+
// }
120+
idx = findFirst(p << 1 | 1, m + 1, r, size); // 递归右子树
121+
}
122+
return idx;
123+
}
124+
}
125+
}
126+
/*
127+
3479. 将水果装入篮子 III
128+
https://leetcode.cn/problems/fruits-into-baskets-iii/description/
129+
130+
第 440 场周赛 T3。
131+
132+
给你两个长度为 n 的整数数组,fruits 和 baskets,其中 fruits[i] 表示第 i 种水果的 数量,baskets[j] 表示第 j 个篮子的 容量。
133+
你需要对 fruits 数组从左到右按照以下规则放置水果:
134+
- 每种水果必须放入第一个 容量大于等于 该水果数量的 最左侧可用篮子 中。
135+
- 每个篮子只能装 一种 水果。
136+
- 如果一种水果 无法放入 任何篮子,它将保持 未放置。
137+
返回所有可能分配完成后,剩余未放置的水果种类的数量。
138+
提示:
139+
n == fruits.length == baskets.length
140+
1 <= n <= 10^5
141+
1 <= fruits[i], baskets[i] <= 10^9
142+
143+
线段树二分。
144+
相似题目: 2502. 设计内存分配器
145+
https://leetcode.cn/problems/design-memory-allocator/
146+
*/
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import java.util.ArrayList;
2+
import java.util.Arrays;
3+
import java.util.List;
4+
5+
public class Solution3480 {
6+
public long maxSubarrays(int n, int[][] conflictingPairs) {
7+
List<Integer>[] groups = new ArrayList[n + 1];
8+
Arrays.setAll(groups, e -> new ArrayList<>());
9+
for (int[] p : conflictingPairs) {
10+
int a = p[0];
11+
int b = p[1];
12+
groups[Math.min(a, b)].add(Math.max(a, b));
13+
}
14+
15+
long ans = 0;
16+
long[] extra = new long[n + 2];
17+
long maxExtra = 0;
18+
// 维护最小 b 和次小 b
19+
int b0 = n + 1;
20+
int b1 = n + 1;
21+
for (int a = n; a > 0; a--) {
22+
List<Integer> listB = groups[a];
23+
for (int b : listB) {
24+
if (b < b0) {
25+
b1 = b0;
26+
b0 = b;
27+
} else if (b < b1) {
28+
b1 = b;
29+
}
30+
}
31+
ans += b0 - a;
32+
extra[b0] += b1 - b0;
33+
maxExtra = Math.max(maxExtra, extra[b0]);
34+
}
35+
36+
return ans + maxExtra;
37+
}
38+
}
39+
/*
40+
3480. 删除一个冲突对后最大子数组数目
41+
https://leetcode.cn/problems/maximize-subarrays-after-removing-one-conflicting-pair/description/
42+
43+
第 440 场周赛 T4。
44+
45+
给你一个整数 n,表示一个包含从 1 到 n 按顺序排列的整数数组 nums。此外,给你一个二维数组 conflictingPairs,其中 conflictingPairs[i] = [a, b] 表示 a 和 b 形成一个冲突对。
46+
从 conflictingPairs 中删除 恰好 一个元素。然后,计算数组 nums 中的非空子数组数量,这些子数组都不能同时包含任何剩余冲突对 [a, b] 中的 a 和 b。
47+
返回删除 恰好 一个冲突对后可能得到的 最大 子数组数量。
48+
子数组 是数组中一个连续的 非空 元素序列。
49+
提示:
50+
2 <= n <= 10^5
51+
1 <= conflictingPairs.length <= 2 * n
52+
conflictingPairs[i].length == 2
53+
1 <= conflictingPairs[i][j] <= n
54+
conflictingPairs[i][0] != conflictingPairs[i][1]
55+
56+
枚举子数组左端点,看看有多少个合法的右端点。
57+
b 的最小值,记作 b0。有 [i,b0-1] 所以有 b0-i.
58+
删除一个冲突对时,b 的次小值,记作 b1,额外增加 b1-b0.
59+
时间复杂度 O(n)。
60+
rating 2647 (clist.by)
61+
*/
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
public class Solution3477Tests {
2+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import org.junit.jupiter.api.Assertions;
2+
import org.junit.jupiter.api.Test;
3+
4+
public class Solution3478Tests {
5+
private final Solution3478 solution3478 = new Solution3478();
6+
7+
@Test
8+
public void example1() {
9+
int[] nums1 = {4, 2, 1, 5, 3};
10+
int[] nums2 = {10, 20, 30, 40, 50};
11+
int k = 2;
12+
long[] expected = {80, 30, 0, 80, 50};
13+
Assertions.assertArrayEquals(expected, solution3478.findMaxSum(nums1, nums2, k));
14+
}
15+
16+
@Test
17+
public void example2() {
18+
int[] nums1 = {2, 2, 2, 2};
19+
int[] nums2 = {3, 1, 2, 3};
20+
int k = 1;
21+
long[] expected = {0, 0, 0, 0};
22+
Assertions.assertArrayEquals(expected, solution3478.findMaxSum(nums1, nums2, k));
23+
}
24+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import org.junit.jupiter.api.Assertions;
2+
import org.junit.jupiter.api.Test;
3+
4+
public class Solution3479Tests {
5+
private final Solution3479 solution3479 = new Solution3479();
6+
7+
@Test
8+
public void example1() {
9+
int[] fruits = {4, 2, 5};
10+
int[] baskets = {3, 5, 4};
11+
int expected = 1;
12+
Assertions.assertEquals(expected, solution3479.numOfUnplacedFruits(fruits, baskets));
13+
}
14+
15+
@Test
16+
public void example2() {
17+
int[] fruits = {3, 6, 1};
18+
int[] baskets = {6, 4, 7};
19+
int expected = 0;
20+
Assertions.assertEquals(expected, solution3479.numOfUnplacedFruits(fruits, baskets));
21+
}
22+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import org.junit.jupiter.api.Assertions;
2+
import org.junit.jupiter.api.Test;
3+
4+
public class Solution3480Tests {
5+
private final Solution3480 solution3480 = new Solution3480();
6+
7+
@Test
8+
public void example1() {
9+
int n = 4;
10+
int[][] conflictingPairs = UtUtils.stringToInts2("[[2,3],[1,4]]");
11+
long expected = 9;
12+
Assertions.assertEquals(expected, solution3480.maxSubarrays(n, conflictingPairs));
13+
}
14+
15+
@Test
16+
public void example2() {
17+
int n = 5;
18+
int[][] conflictingPairs = UtUtils.stringToInts2("[[1,2],[2,5],[3,5]]");
19+
long expected = 12;
20+
Assertions.assertEquals(expected, solution3480.maxSubarrays(n, conflictingPairs));
21+
}
22+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /