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 ba018f2

Browse files
committed
第157场双周赛T1~T4 & 第451场周赛T1~T4 (8)
1 parent 3b6b5c6 commit ba018f2

16 files changed

+716
-0
lines changed
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import java.util.TreeSet;
2+
3+
public class Solution3556 {
4+
public long sumOfLargestPrimes(String S) {
5+
char[] s = S.toCharArray();
6+
TreeSet<Long> set = new TreeSet<>();
7+
for (int i = 0; i < s.length; i++) {
8+
long x = 0;
9+
for (int j = i; j < s.length; j++) {
10+
x = x * 10 + (s[j] - '0');
11+
if (isPrime(x)) {
12+
set.add(x);
13+
}
14+
}
15+
}
16+
17+
return set.descendingSet()
18+
.stream()
19+
.limit(3)
20+
.mapToLong(Long::longValue)
21+
.sum();
22+
}
23+
24+
private boolean isPrime(long num) {
25+
if (num < 2) {
26+
return false;
27+
}
28+
for (long i = 2; i * i <= num; ++i) {
29+
if (num % i == 0) {
30+
return false;
31+
}
32+
}
33+
return true;
34+
}
35+
}
36+
/*
37+
3556. 最大质数子字符串之和
38+
https://leetcode.cn/problems/sum-of-largest-prime-substrings/description/
39+
40+
第 157 场双周赛 T1。
41+
42+
给定一个字符串 s,找出可以由其 子字符串 组成的 3个最大的不同质数 的和。
43+
返回这些质数的 总和 ,如果少于 3 个不同的质数,则返回 所有 不同质数的和。
44+
质数是大于 1 且只有两个因数的自然数:1和它本身。
45+
子字符串 是字符串中的一个连续字符序列。
46+
注意:每个质数即使出现在 多个 子字符串中,也只能计算 一次 。此外,将子字符串转换为整数时,忽略任何前导零。
47+
提示:
48+
1 <= s.length <= 10
49+
s 仅由数字组成。
50+
51+
模拟。
52+
*/
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import java.util.Arrays;
2+
3+
public class Solution3557 {
4+
public int maxSubstrings(String word) {
5+
char[] s = word.toCharArray();
6+
int n = s.length;
7+
int ans = 0;
8+
int[] pos = new int[26];
9+
Arrays.fill(pos, -1);
10+
for (int i = 0; i < n; i++) {
11+
int ch = s[i] - 'a';
12+
if (pos[ch] == -1) {
13+
pos[ch] = i;
14+
} else if (i - pos[ch] > 2) {
15+
ans++;
16+
Arrays.fill(pos, -1);
17+
}
18+
}
19+
return ans;
20+
}
21+
}
22+
/*
23+
3557. 不相交子字符串的最大数量
24+
https://leetcode.cn/problems/find-maximum-number-of-non-intersecting-substrings/description/
25+
26+
第 157 场双周赛 T2。
27+
28+
给你一个字符串 word。
29+
返回以 首尾字母相同 且 长度至少为 4 的 不相交子字符串 的最大数量。
30+
子字符串 是字符串中连续的 非空 字符序列。
31+
提示:
32+
1 <= word.length <= 2 * 10^5
33+
word 仅由小写英文字母组成。
34+
35+
划分型贪心。
36+
时间复杂度 O(26n)。
37+
*/
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import java.util.ArrayList;
2+
import java.util.Arrays;
3+
import java.util.List;
4+
5+
public class Solution3558 {
6+
private List<Integer>[] g;
7+
8+
public int assignEdgeWeights(int[][] edges) {
9+
int n = edges.length + 1;
10+
g = new ArrayList[n + 1];
11+
Arrays.setAll(g, e -> new ArrayList<>());
12+
for (int[] e : edges) {
13+
int x = e[0], y = e[1];
14+
g[x].add(y);
15+
g[y].add(x);
16+
}
17+
int k = dfs(1, 0);
18+
return (int) quickPow(2, k - 1);
19+
}
20+
21+
private int dfs(int x, int fa) {
22+
int d = 0;
23+
for (int y : g[x]) {
24+
if (y != fa) { // 不递归到父节点
25+
d = Math.max(d, dfs(y, x) + 1);
26+
}
27+
}
28+
return d;
29+
}
30+
31+
static final int MOD = (int) (1e9 + 7);
32+
33+
// 快速幂 res = a^b % mod
34+
private long quickPow(long a, long b) {
35+
long res = 1L;
36+
while (b > 0) {
37+
if ((b & 1) != 0) res = res * a % MOD;
38+
a = a * a % MOD;
39+
b >>= 1;
40+
}
41+
return res;
42+
}
43+
}
44+
/*
45+
3558. 给边赋权值的方案数 I
46+
https://leetcode.cn/problems/number-of-ways-to-assign-edge-weights-i/description/
47+
48+
第 157 场双周赛 T3。
49+
50+
给你一棵 n 个节点的无向树,节点从 1 到 n 编号,树以节点 1 为根。树由一个长度为 n - 1 的二维整数数组 edges 表示,其中 edges[i] = [ui, vi] 表示在节点 ui 和 vi 之间有一条边。
51+
一开始,所有边的权重为 0。你可以将每条边的权重设为 1 或 2。
52+
两个节点 u 和 v 之间路径的 代价 是连接它们路径上所有边的权重之和。
53+
选择任意一个 深度最大 的节点 x。返回从节点 1 到 x 的路径中,边权重之和为 奇数 的赋值方式数量。
54+
由于答案可能很大,返回它对 10^9 + 7 取模的结果。
55+
注意: 忽略从节点 1 到节点 x 的路径外的所有边。
56+
提示:
57+
2 <= n <= 10^5
58+
edges.length == n - 1
59+
edges[i] == [ui, vi]
60+
1 <= ui, vi <= n
61+
edges 表示一棵合法的树。
62+
63+
从 k 个数中选奇数个数的方案数。
64+
答案为 2^{k-1} % mod。
65+
相似题目: 3559. 给边赋权值的方案数 II
66+
https://leetcode.cn/problems/number-of-ways-to-assign-edge-weights-ii/description/
67+
*/
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
import java.util.ArrayList;
2+
import java.util.Arrays;
3+
import java.util.List;
4+
5+
public class Solution3559 {
6+
static final int MOD = (int) (1e9 + 7);
7+
8+
// 快速幂 res = a^b % mod
9+
private long quickPow(long a, long b) {
10+
long res = 1L;
11+
while (b > 0) {
12+
if ((b & 1) != 0) res = res * a % MOD;
13+
a = a * a % MOD;
14+
b >>= 1;
15+
}
16+
return res;
17+
}
18+
19+
private List<Integer>[] g;
20+
private int dfn;
21+
private int[][] nodes; // l, r
22+
private final int mx = 17;
23+
private int[][] pa;
24+
private int[] dep;
25+
26+
public int[] assignEdgeWeights(int[][] edges, int[][] queries) {
27+
int n = edges.length + 1;
28+
g = new ArrayList[n + 1];
29+
Arrays.setAll(g, e -> new ArrayList<>());
30+
for (int[] e : edges) {
31+
int x = e[0] - 1, y = e[1] - 1;
32+
g[x].add(y);
33+
g[y].add(x);
34+
}
35+
dfn = 0;
36+
nodes = new int[n][2];
37+
pa = new int[n][mx];
38+
dep = new int[n];
39+
build(0, -1);
40+
for (int i = 0; i + 1 < mx; i++) {
41+
for (int v = 0; v < pa.length; v++) {
42+
int p = pa[v][i];
43+
if (p != -1) {
44+
pa[v][i + 1] = pa[p][i];
45+
} else {
46+
pa[v][i + 1] = -1;
47+
}
48+
}
49+
}
50+
51+
int q = queries.length;
52+
int[] ans = new int[q];
53+
for (int i = 0; i < q; i++) {
54+
int k = get_path_sum(queries[i][0] - 1, queries[i][1] - 1);
55+
if (k == 0) continue;
56+
ans[i] = (int) quickPow(2, k - 1);
57+
}
58+
return ans;
59+
}
60+
61+
int get_path_sum(int u, int v) {
62+
int ancestor = getLCA(u, v);
63+
return dep[u] + dep[v] - 2 * dep[ancestor];
64+
}
65+
66+
int build(int v, int fa) {
67+
dfn++;
68+
nodes[v][0] = dfn;
69+
pa[v][0] = fa;
70+
int sz = 1;
71+
for (int w : g[v]) {
72+
if (w != fa) {
73+
dep[w] = dep[v] + 1;
74+
sz += build(w, v);
75+
}
76+
}
77+
nodes[v][1] = nodes[v][0] + sz - 1;
78+
return sz;
79+
}
80+
81+
int uptoDep(int v, int d) {
82+
for (int k = dep[v] - d; k > 0; k &= k - 1) {
83+
v = pa[v][Integer.numberOfTrailingZeros(k)];
84+
}
85+
return v;
86+
}
87+
88+
int getLCA(int v, int w) {
89+
if (dep[v] > dep[w]) {
90+
int tmp = v;
91+
v = w;
92+
w = tmp;
93+
}
94+
w = uptoDep(w, dep[v]);
95+
if (w == v) return v;
96+
for (int i = mx - 1; i >= 0; i--) {
97+
if (pa[v][i] != pa[w][i]) {
98+
v = pa[v][i];
99+
w = pa[w][i];
100+
}
101+
}
102+
return pa[v][0];
103+
}
104+
}
105+
/*
106+
3559. 给边赋权值的方案数 II
107+
https://leetcode.cn/problems/number-of-ways-to-assign-edge-weights-ii/description/
108+
109+
第 157 场双周赛 T4。
110+
111+
给你一棵有 n 个节点的无向树,节点从 1 到 n 编号,树以节点 1 为根。树由一个长度为 n - 1 的二维整数数组 edges 表示,其中 edges[i] = [ui, vi] 表示在节点 ui 和 vi 之间有一条边。
112+
一开始,所有边的权重为 0。你可以将每条边的权重设为 1 或 2。
113+
两个节点 u 和 v 之间路径的 代价 是连接它们路径上所有边的权重之和。
114+
给定一个二维整数数组 queries。对于每个 queries[i] = [ui, vi],计算从节点 ui 到 vi 的路径中,使得路径代价为 奇数 的权重分配方式数量。
115+
返回一个数组 answer,其中 answer[i] 表示第 i 个查询的合法赋值方式数量。
116+
由于答案可能很大,请对每个 answer[i] 取模 10^9 + 7。
117+
注意: 对于每个查询,仅考虑 ui 到 vi 路径上的边,忽略其他边。
118+
提示:
119+
2 <= n <= 10^5
120+
edges.length == n - 1
121+
edges[i] == [ui, vi]
122+
1 <= queries.length <= 10^5
123+
queries[i] == [ui, vi]
124+
1 <= ui, vi <= n
125+
edges 表示一棵合法的树。
126+
127+
最近公共祖先 LCA。
128+
答案为 2^{k-1} % mod。k 为两点之间的距离(边数),套 LCA 模板即可。
129+
相似题目: 3553. 包含给定路径的最小带权子树 II
130+
https://leetcode.cn/problems/minimum-weighted-subgraph-with-the-required-paths-ii/description/
131+
rating 2509 (clist.by)
132+
*/
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
public class Solution3560 {
2+
public long minCuttingCost(int n, int m, int k) {
3+
long ans1 = Math.max((long) (n - k) * k, 0);
4+
long ans2 = Math.max((long) (m - k) * k, 0);
5+
return Math.max(ans1, ans2);
6+
}
7+
}
8+
/*
9+
3560. 木材运输的最小成本
10+
https://leetcode.cn/problems/find-minimum-log-transportation-cost/description/
11+
12+
第 451 场周赛 T1。
13+
14+
给你三个整数 n、m 和 k。
15+
有两根长度分别为 n 和 m 单位的木材,需要通过三辆卡车运输。每辆卡车最多只能装载一根长度 不超过 k 单位的木材。
16+
你可以将木材切成更小的段,其中将长度为 x 的木材切割成长度为 len1 和 len2 的段的成本为 cost = len1 * len2,并且满足 len1 + len2 = x。
17+
返回将木材分配到卡车上的 最小总成本 。如果木材不需要切割,总成本为 0。
18+
提示:
19+
2 <= k <= 10^5
20+
1 <= n, m <= 2 * k
21+
输入数据保证木材总存在能被运输的方案。
22+
23+
分类讨论。
24+
*/
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
public class Solution3561 {
2+
public String resultingString(String s) {
3+
StringBuilder ans = new StringBuilder();
4+
for (char c : s.toCharArray()) {
5+
if (!ans.isEmpty() && (Math.abs(ans.charAt(ans.length() - 1) - c) == 1 || Math.abs(ans.charAt(ans.length() - 1) - c) == 25)) {
6+
ans.deleteCharAt(ans.length() - 1);
7+
} else {
8+
ans.append(c);
9+
}
10+
}
11+
return ans.toString();
12+
}
13+
}
14+
/*
15+
3561. 移除相邻字符
16+
https://leetcode.cn/problems/resulting-string-after-adjacent-removals/description/
17+
18+
第 451 场周赛 T2。
19+
20+
给你一个由小写英文字母组成的字符串 s。
21+
你 必须 在字符串 s 中至少存在两个 连续 字符时,反复执行以下操作:
22+
- 移除字符串中 最左边 的一对按照字母表 连续 的相邻字符(无论是按顺序还是逆序,例如 'a' 和 'b',或 'b' 和 'a')。
23+
- 将剩余字符向左移动以填补空隙。
24+
当无法再执行任何操作时,返回最终的字符串。
25+
注意:字母表是循环的,因此 'a' 和 'z' 也视为连续。
26+
提示:
27+
1 <= s.length <= 10^5
28+
s 仅由小写英文字母组成。
29+
30+
栈模拟。
31+
*/

0 commit comments

Comments
(0)

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