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 c53d177

Browse files
committed
第148场双周赛T1~T4 & 第433场周赛T1~T4 (8)
1 parent e1cb4c3 commit c53d177

16 files changed

+626
-0
lines changed
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
public class Solution3423 {
2+
public int maxAdjacentDistance(int[] nums) {
3+
int n = nums.length;
4+
int ans = Math.abs(nums[0] - nums[n - 1]);
5+
for (int i = 1; i < n; i++) {
6+
ans = Math.max(ans, Math.abs(nums[i] - nums[i - 1]));
7+
}
8+
return ans;
9+
}
10+
}
11+
/*
12+
3423. 循环数组中相邻元素的最大差值
13+
https://leetcode.cn/problems/maximum-difference-between-adjacent-elements-in-a-circular-array/description/
14+
15+
第 148 场双周赛 T1。
16+
17+
给你一个 循环 数组 nums ,请你找出相邻元素之间的 最大 绝对差值。
18+
注意:一个循环数组中,第一个元素和最后一个元素是相邻的。
19+
提示:
20+
2 <= nums.length <= 100
21+
-100 <= nums[i] <= 100
22+
23+
模拟。
24+
*/
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import java.util.Arrays;
2+
3+
public class Solution3424 {
4+
public long minCost(int[] arr, int[] brr, long k) {
5+
long ans1 = getAns(arr, brr);
6+
Arrays.sort(arr);
7+
Arrays.sort(brr);
8+
long ans2 = getAns(arr, brr) + k;
9+
return Math.min(ans1, ans2);
10+
}
11+
12+
private long getAns(int[] arr, int[] brr) {
13+
int n = arr.length;
14+
long ans = 0;
15+
for (int i = 0; i < n; i++) {
16+
ans += Math.abs(arr[i] - brr[i]);
17+
}
18+
return ans;
19+
}
20+
}
21+
/*
22+
3424. 将数组变相同的最小代价
23+
https://leetcode.cn/problems/minimum-cost-to-make-arrays-identical/description/
24+
25+
第 148 场双周赛 T2。
26+
27+
给你两个长度都为 n 的整数数组 arr 和 brr 以及一个整数 k 。你可以对 arr 执行以下操作任意次:
28+
- 将 arr 分割成若干个 连续的 子数组,并将这些子数组按任意顺序重新排列。这个操作的代价为 k 。
29+
- 选择 arr 中的任意一个元素,将它增加或者减少一个正整数 x 。这个操作的代价为 x 。
30+
请你返回将 arr 变为 brr 的 最小 总代价。
31+
子数组 是一个数组中一段连续 非空 的元素序列。
32+
提示:
33+
1 <= arr.length == brr.length <= 10^5
34+
0 <= k <= 2 * 10^10
35+
-10^5 <= arr[i] <= 10^5
36+
-10^5 <= brr[i] <= 10^5
37+
38+
贪心。用交换论证法可以证明这样做是最优的。
39+
时间复杂度 O(nlogn)。
40+
*/
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
import java.util.ArrayList;
2+
import java.util.Arrays;
3+
import java.util.HashMap;
4+
import java.util.List;
5+
import java.util.Map;
6+
7+
public class Solution3425 {
8+
private int[] nums;
9+
private List<int[]>[] g;
10+
private List<Integer> dis;
11+
private Map<Integer, Integer> lastDepth;
12+
private int maxLen, minNodes;
13+
14+
public int[] longestSpecialPath(int[][] edges, int[] nums) {
15+
this.nums = nums;
16+
int n = edges.length + 1;
17+
g = new ArrayList[n];
18+
Arrays.setAll(g, e -> new ArrayList<>());
19+
for (int[] e : edges) {
20+
int u = e[0], v = e[1], wt = e[2];
21+
g[u].add(new int[]{v, wt});
22+
g[v].add(new int[]{u, wt});
23+
}
24+
25+
dis = new ArrayList<>();
26+
dis.add(0);
27+
lastDepth = new HashMap<>();
28+
maxLen = -1;
29+
minNodes = 0;
30+
dfs(0, -1, 0);
31+
return new int[]{maxLen, minNodes};
32+
}
33+
34+
private void dfs(int x, int fa, int topDepth) {
35+
int color = nums[x];
36+
int oldDepth = lastDepth.getOrDefault(color, 0);
37+
topDepth = Math.max(topDepth, oldDepth);
38+
39+
int disX = dis.getLast();
40+
int len = disX - dis.get(topDepth);
41+
int nodes = dis.size() - topDepth;
42+
if (len > maxLen || len == maxLen && nodes < minNodes) {
43+
maxLen = len;
44+
minNodes = nodes;
45+
}
46+
47+
lastDepth.put(color, dis.size());
48+
for (int[] e : g[x]) {
49+
int y = e[0];
50+
if (y != fa) { // 避免访问父节点
51+
dis.add(disX + e[1]);
52+
dfs(y, x, topDepth);
53+
dis.removeLast(); // 恢复现场
54+
}
55+
}
56+
lastDepth.put(color, oldDepth); // 恢复现场
57+
}
58+
}
59+
/*
60+
3425. 最长特殊路径
61+
https://leetcode.cn/problems/longest-special-path/description/
62+
63+
第 148 场双周赛 T3。
64+
65+
给你一棵根节点为节点 0 的无向树,树中有 n 个节点,编号为 0 到 n - 1 ,这棵树通过一个长度为 n - 1 的二维数组 edges 表示,其中 edges[i] = [ui, vi, lengthi] 表示节点 ui 和 vi 之间有一条长度为 lengthi 的边。同时给你一个整数数组 nums ,其中 nums[i] 表示节点 i 的值。
66+
特殊路径 指的是树中一条从祖先节点 往下 到后代节点且经过节点的值 互不相同 的路径。
67+
注意 ,一条路径可以开始和结束于同一节点。
68+
请你返回一个长度为 2 的数组 result ,其中 result[0] 是 最长 特殊路径的 长度 ,result[1] 是所有 最长特殊路径中的 最少 节点数目。
69+
提示:
70+
2 <= n <= 5 * 10^4
71+
edges.length == n - 1
72+
edges[i].length == 3
73+
0 <= ui, vi < n
74+
1 <= lengthi <= 10^3
75+
nums.length == n
76+
0 <= nums[i] <= 5 * 10^4
77+
输入保证 edges 表示一棵合法的树。
78+
79+
树上滑窗。
80+
时间复杂度 O(n)。
81+
rating 2715 (clist.by)
82+
*/
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
public class Solution3426 {
2+
static final int MOD = (int) (1e9 + 7);
3+
static final int MX = (int) (1e5 + 5);
4+
static Comb comb = new Comb(MX);
5+
6+
public int distanceSum(int m, int n, int k) {
7+
long ans = (m * n * (m * ((long) n * n - 1) + n * ((long) m * m - 1))) / 6 % MOD * comb.binom(m * n - 2, k - 2) % MOD;
8+
return (int) ans;
9+
}
10+
11+
static class Comb {
12+
long[] fac, inv_fac;
13+
14+
public Comb(int n) {
15+
fac = new long[n + 1];
16+
fac[0] = 1;
17+
for (int i = 1; i <= n; i++) fac[i] = fac[i - 1] * i % MOD;
18+
inv_fac = new long[n + 1];
19+
for (int i = 0; i <= n; i++) inv_fac[i] = quickPow(fac[i], MOD - 2);
20+
}
21+
22+
// C(n, m) = n! / m!(n-m)!
23+
long binom(int n, int m) {
24+
if (n < m || m < 0) return 0;
25+
return fac[n] * inv_fac[m] % MOD * inv_fac[n - m] % MOD;
26+
}
27+
28+
// 模下的 a^b
29+
long quickPow(long a, long b) {
30+
long res = 1L;
31+
while (b > 0) {
32+
if ((b & 1) != 0) res = res * a % MOD;
33+
a = a * a % MOD;
34+
b >>= 1;
35+
}
36+
return res;
37+
}
38+
}
39+
}
40+
/*
41+
3426. 所有安放棋子方案的曼哈顿距离
42+
https://leetcode.cn/problems/manhattan-distances-of-all-arrangements-of-pieces/description/
43+
44+
第 148 场双周赛 T4。
45+
46+
给你三个整数 m ,n 和 k 。
47+
给你一个大小为 m x n 的矩形格子,它包含 k 个没有差别的棋子。请你返回所有放置棋子的 合法方案 中,每对棋子之间的曼哈顿距离之和。
48+
一个 合法方案 指的是将所有 k 个棋子都放在格子中且一个格子里 至多 只有一个棋子。
49+
由于答案可能很大, 请你将它对 109 + 7 取余 后返回。
50+
两个格子 (xi, yi) 和 (xj, yj) 的曼哈顿距离定义为 |xi - xj| + |yi - yj| 。
51+
提示:
52+
1 <= m, n <= 10^5
53+
2 <= m * n <= 10^5
54+
2 <= k <= m * n
55+
56+
贡献法。
57+
https://leetcode.cn/problems/manhattan-distances-of-all-arrangements-of-pieces/solutions/3051398/gong-xian-fa-yu-chu-li-hou-o1pythonjavac-2hgt/
58+
最终答案为 \binom{mn-2}{k-2} \left (m^2 \binom{n+1}{3} + n^2\binom{m+1}{3} \right )
59+
组合数的 苏联记法 与 美式记法。
60+
rating 2738 (clist.by)
61+
*/
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
public class Solution3427 {
2+
public int subarraySum(int[] nums) {
3+
int n = nums.length;
4+
int[] ps = new int[n + 1];
5+
for (int i = 0; i < n; i++) {
6+
ps[i + 1] = ps[i] + nums[i];
7+
}
8+
9+
int ans = 0;
10+
for (int i = 0; i < n; i++) {
11+
int L = Math.max(0, i - nums[i]);
12+
ans += ps[i + 1] - ps[L];
13+
}
14+
return ans;
15+
}
16+
}
17+
/*
18+
3427. 变长子数组求和
19+
https://leetcode.cn/problems/sum-of-variable-length-subarrays/description/
20+
21+
第 433 场周赛 T1。
22+
23+
给你一个长度为 n 的整数数组 nums 。对于 每个 下标 i(0 <= i < n),定义对应的子数组 nums[start ... i](start = max(0, i - nums[i]))。
24+
返回为数组中每个下标定义的子数组中所有元素的总和。
25+
子数组 是数组中的一个连续、非空 的元素序列。
26+
提示:
27+
1 <= n == nums.length <= 100
28+
1 <= nums[i] <= 1000
29+
30+
前缀和模拟。
31+
时间复杂度 O(n)。
32+
*/
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import java.util.Arrays;
2+
3+
public class Solution3428 {
4+
static final int MOD = (int) (1e9 + 7);
5+
static final int MX = (int) (1e5 + 5);
6+
static Comb comb = new Comb(MX);
7+
8+
public int minMaxSums(int[] nums, int k) {
9+
Arrays.sort(nums);
10+
int n = nums.length;
11+
long ans = 0;
12+
for (int i = 0; i < n; i++) {
13+
long s = 0;
14+
for (int j = 0; j < Math.min(k, i + 1); j++) {
15+
s += comb.binom(i, j);
16+
}
17+
ans = (ans + s % MOD * (nums[i] + nums[n - 1 - i])) % MOD;
18+
}
19+
return (int) ans;
20+
}
21+
22+
static class Comb {
23+
long[] fac, inv_fac;
24+
25+
public Comb(int n) {
26+
fac = new long[n + 1];
27+
fac[0] = 1;
28+
for (int i = 1; i <= n; i++) fac[i] = fac[i - 1] * i % MOD;
29+
inv_fac = new long[n + 1];
30+
for (int i = 0; i <= n; i++) inv_fac[i] = quickPow(fac[i], MOD - 2);
31+
}
32+
33+
// C(n, m) = n! / m!(n-m)!
34+
long binom(int n, int m) {
35+
if (n < m || m < 0) return 0;
36+
return fac[n] * inv_fac[m] % MOD * inv_fac[n - m] % MOD;
37+
}
38+
39+
// 模下的 a^b
40+
long quickPow(long a, long b) {
41+
long res = 1L;
42+
while (b > 0) {
43+
if ((b & 1) != 0) res = res * a % MOD;
44+
a = a * a % MOD;
45+
b >>= 1;
46+
}
47+
return res;
48+
}
49+
}
50+
}
51+
/*
52+
3428. 最多 K 个元素的子序列的最值之和
53+
https://leetcode.cn/problems/maximum-and-minimum-sums-of-at-most-size-k-subsequences/description/
54+
55+
第 433 场周赛 T2。
56+
57+
给你一个整数数组 nums 和一个正整数 k,返回所有长度最多为 k 的 子序列 中 最大值 与 最小值 之和的总和。
58+
非空子序列 是指从另一个数组中删除一些或不删除任何元素(且不改变剩余元素的顺序)得到的数组。
59+
由于答案可能非常大,请返回对 10^9 + 7 取余数的结果。
60+
提示:
61+
1 <= nums.length <= 10^5
62+
0 <= nums[i] <= 10^9
63+
1 <= k <= min(100, nums.length)
64+
65+
贡献法 + 组合数学 + 递推优化。
66+
我们可以从下标 [0,i−1] 中选至多 min(k−1,i) 个数,作为子序列的其他元素。这样的选法总共有
67+
\sum_{j=0}^{min(k-1,i)} \binom{i}{j}
68+
相似题目: 3430. 最多 K 个元素的子数组的最值之和
69+
https://leetcode.cn/problems/maximum-and-minimum-sums-of-at-most-size-k-subarrays/description/
70+
*/
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import java.util.Arrays;
2+
3+
public class Solution3429 {
4+
private int[][] cost;
5+
private long[][][] memo;
6+
7+
public long minCost(int n, int[][] cost) {
8+
this.cost = cost;
9+
memo = new long[n / 2][4][4];
10+
for (int i = 0; i < n / 2; i++) {
11+
for (int j = 0; j < 4; j++) {
12+
Arrays.fill(memo[i][j], -1);
13+
}
14+
}
15+
return dfs(n / 2 - 1, 3, 3);
16+
}
17+
18+
private long dfs(int i, int preJ, int preK) {
19+
if (i < 0) return 0;
20+
if (memo[i][preJ][preK] != -1) return memo[i][preJ][preK];
21+
long res = Long.MAX_VALUE;
22+
for (int j = 0; j < 3; j++) {
23+
if (j == preJ) continue;
24+
for (int k = 0; k < 3; k++) {
25+
if (k != preK && k != j) {
26+
long res2 = dfs(i - 1, j, k) + cost[i][j] + cost[cost.length - 1 - i][k];
27+
res = Math.min(res, res2);
28+
}
29+
}
30+
}
31+
return memo[i][preJ][preK] = res;
32+
}
33+
}
34+
/*
35+
3429. 粉刷房子 IV
36+
https://leetcode.cn/problems/paint-house-iv/description/
37+
38+
第 433 场周赛 T3。
39+
40+
给你一个 偶数 整数 n,表示沿直线排列的房屋数量,以及一个大小为 n x 3 的二维数组 cost,其中 cost[i][j] 表示将第 i 个房屋涂成颜色 j + 1 的成本。
41+
如果房屋满足以下条件,则认为它们看起来 漂亮:
42+
- 不存在 两个 涂成相同颜色的相邻房屋。
43+
- 距离行两端 等距 的房屋不能涂成相同的颜色。例如,如果 n = 6,则位置 (0, 5)、(1, 4) 和 (2, 3) 的房屋被认为是等距的。
44+
返回使房屋看起来 漂亮 的 最低 涂色成本。
45+
提示:
46+
2 <= n <= 10^5
47+
n 是偶数。
48+
cost.length == n
49+
cost[i].length == 3
50+
0 <= cost[i][j] <= 10^5
51+
52+
多维 DP。
53+
时间复杂度 O(n * k^4)。
54+
rating 2170 (clist.by)
55+
*/

0 commit comments

Comments
(0)

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