# 第 250 场周赛题解
# Q1 1935. 可以输入的最大单词数 (opens new window)
直接算就行,这就是舒服的地方。
class Solution5161 {
fun canBeTypedWords(text: String, brokenLetters: String): Int {
return text.split(" ").count {
it.all { it !in brokenLetters }
}
}
}
1
2
3
4
5
6
7
2
3
4
5
6
7
# Q2 1936. 新增的最少台阶数 (opens new window)
算两个间距之间的差,再除。注意刚好整除的情况需要额外减一,直接通过原值减一来实现...
class Solution5814 {
fun addRungs(rungs: IntArray, dist: Int): Int {
var cur = 0
var ans = 0
for (rung in rungs) {
ans += (rung - cur - 1) / dist
cur = rung
}
return ans
}
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
# Q3 1937. 扣分后的最大得分 (opens new window)
比赛时直接生做,时间复杂度是,会超时...
需要把第二层的计算时间复杂度压缩。利用左侧、右侧的性质,把上一行从左看、从右看的最大值列出来,然后每一个位置都取其最大值。
之前有题目也是利用左右两边开始的数组,可惜比赛时没想到... 吸取教训!
class Solution5815 {
// 左侧、右侧数组
fun maxPoints(points: Array<IntArray>): Long {
val n = points.size
val m = points[0].size
var dp = points[0].map { it.toLong() }.toLongArray()
for (i in 1 until n) {
val next = LongArray(m)
// 左侧最大值
var lmax = 0L
for (j in 0 until m) {
lmax = maxOf(lmax - 1, dp[j])
next[j] = maxOf(next[j], lmax)
}
// 右侧最大值
var rmax = 0L
for (j in m - 1 downTo 0) {
rmax = maxOf(rmax - 1, dp[j])
next[j] = maxOf(next[j], rmax)
}
for (j in 0 until m) {
next[j] += points[i][j].toLong()
}
dp = next
}
return dp.max()!!
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# Q4 1938. 查询最大基因差 (opens new window)
这道题很可惜了,题目一眼就看出来是用字典树+离线算法... 可惜之前没有处理字典树的删除操作... 结果每次新建树,会超时...
这次把字典树的删除操作补上,每一位记录当前的值。新增的时候加1,删除的时候减一,然后进行判断的时候,该节点是否存在依赖其是否为0。
class Solution5816 {
fun maxGeneticDifference(parents: IntArray, queries: Array<IntArray>): IntArray {
val map = HashMap<Int, ArrayList<Int>>()
for (i in parents.indices) {
map[parents[i]] = map.getOrDefault(parents[i], arrayListOf())
map[parents[i]]!!.add(i)
}
val queryMap = HashMap<Int, ArrayList<Pair<Int, Int>>>()
for (i in queries.indices) {
queryMap[queries[i][0]] = queryMap.getOrDefault(queries[i][0], arrayListOf())
queryMap[queries[i][0]]!!.add(Pair(queries[i][1], i))
}
val ans = IntArray(queries.size)
fun dfs(cur: Int, trie: Trie<Int>) {
queryMap[cur]?.forEach {
ans[it.second] = trie.maxXor(it.first)
}
map[cur]?.forEach {
trie.insertInt(it)
dfs(it, trie)
trie.removeInt(it)
}
}
dfs(-1, Trie<Int>())
return ans
}
}
class Trie<T> {
/**
* @param cnt 记录当前点的值,用于Remove操作
* */
class TrieNode<T>(val init: T? = null, var cnt: Int = 0) {
val value: T? = init
val children: ArrayList<TrieNode<T>> = arrayListOf()
var isEnd = false
}
var root = TrieNode<T>()
/**
* insert value
* */
fun insert(value: Array<T>) {
fun dfs(node: TrieNode<T>, depth: Int) {
if (depth == value.size) node.isEnd = true
if (depth !in value.indices) return
if (!node.children.map { it.value }.contains(value[depth])) {
node.children.add(TrieNode<T>(value[depth]))
}
val next = node.children.first { it.value == value[depth] }
dfs(next, depth + 1)
}
dfs(root, 0)
}
fun <T> search(target: Array<T>): Boolean {
fun <T> dfs(node: TrieNode<T>, i: Int): Boolean {
if (i in target.indices) {
if (target[i] != node.value)
return false
}
if (i == target.lastIndex) return node.isEnd
node.children.forEach {
if (dfs(it, i + 1)) {
return true
}
}
return false
}
return dfs(root, -1)
}
}
fun Trie<Int>.removeInt(n: Int) {
var temp = this.root
for (i in 31 downTo 0) {
val x: Int = (n shr i) and 1
val item = temp.children.first { it.value == x }
item.cnt--
temp = item
}
}
fun Trie<Int>.insertInt(n: Int) {
var temp = this.root
for (i in 31 downTo 0) {
val x: Int = (n shr i) and 1
val item = temp.children.firstOrNull { it.value == x }
if (item == null)
temp.children.add(Trie.TrieNode(x, 1))
else
item.cnt++
temp = temp.children.first { it.value == x }
}
}
/**
* https://www.geeksforgeeks.org/maximum-possible-xor-every-element-array-another-array/
* */
fun Trie<Int>.maxXor(key: Int): Int {
if (root.children.isEmpty()) return -1
var temp = root
var cur = 0
for (i in 31 downTo 0) {
cur *= 2
val curBit = (key and (1 shl i)).let { if (it > 0) 1 else 0 }
temp = if (temp.children.firstOrNull { it.value == 1 - curBit && it.cnt != 0 } != null)
temp.children.first { it.value == 1 - curBit && it.cnt != 0 }
else
temp.children.first { it.value == curBit && it.cnt != 0 }
cur += curBit xor temp.value!!
}
return cur
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120