# 第 63 场双周赛题解

# Q1 2037. 使每位学生都有座位的最少移动次数 (opens new window)

签到。

class Solution5885 {
    fun minMovesToSeat(seats: IntArray, students: IntArray): Int {
        seats.sort()
        students.sort()
        var ans = 0
        for (i in seats.indices) {
            ans += abs(seats[i] - students[i])
        }
        return ans
    }
}
1
2
3
4
5
6
7
8
9
10
11

# Q2 2038. 如果相邻两个颜色均相同则删除当前颜色 (opens new window)

直接计算有多少可删的即可。

class Solution5886 {
    fun winnerOfGame(colors: String): Boolean {
        var a = 0
        var b = 0
        for (i in colors.indices) {
            if (colors[i] == 'A' &&
                colors.getOrElse(i + 1) { ' ' } == 'A' &&
                colors.getOrElse(i - 1) { ' ' } == 'A'
            ) a++
            if (colors[i] == 'B' &&
                colors.getOrElse(i + 1) { ' ' } == 'B' &&
                colors.getOrElse(i - 1) { ' ' } == 'B'
            ) b++
        }
        if (a > b) return true
        return false
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# Q3 2039. 网络空闲的时刻 (opens new window)

就是单源最短路径,恶心在边界条件最后一次发射时间刚好消息回来的时候,这个时候不用发射... 继续WA。

class Solution5888 {
    fun networkBecomesIdle(edges: Array<IntArray>, patience: IntArray): Int {
        val n = patience.size
        val g = Graph(n)
        edges.forEach {
            g.addEdge(it[0], it[1], 1)
        }
        val dis = g.dijkstra(0)
        var ans = 0L
        for (i in 1 until n) {
            if (dis[i] * 2 > patience[i]) {
                // 最后一次发射时间
                var cur = (dis[i] * 2 / patience[i]) * patience[i]
                if (dis[i] * 2 % patience[i] == 0L) {
                    cur -= patience[i].toLong()
                }
                ans = maxOf(ans, cur + dis[i] * 2 + 1)
            } else {
                ans = maxOf(ans, dis[i] * 2 + 1)
            }
        }
        return ans.toInt()
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

# Q4 2040. 两个有序数组的第 K 小乘积 (opens new window)

直接用二分套二分... 这个方法是没想出来的.. 还打算分四个象限快筛,最后发现过滤不动...

class Solution5887 {
    fun kthSmallestProduct(nums1: IntArray, nums2: IntArray, k: Long): Long {

        val arr1 = if (nums1.size < nums2.size) nums1 else nums2
        val arr2 = if (nums1.size >= nums2.size) nums1 else nums2

        val reversed = arr2.reversed().toIntArray()

        // 计算比 <= mid的值有多少个,刚好为K个的mid即所求
        fun count(mid: Long): Long {
            var c = 0L
            arr1.forEach { n1 ->
                if (n1 >= 0) {
                    c += arr2.biLastIndexOf { n2 ->
                        n1.toLong() * n2.toLong() <= mid
                    } + 1
                } else {
                    c += reversed.biLastIndexOf { n2 ->
                        n1.toLong() * n2.toLong() <= mid
                    } + 1
                }
            }
            return c
        }

        val edges = arrayOf(
            arr1.first().toLong() * arr2.first(),
            arr1.last().toLong() * arr2.first(),
            arr1.first().toLong() * arr2.last(),
            arr1.last().toLong() * arr2.last(),
        )
        var left = edges.minOrNull()!! - 1
        var right = edges.maxOrNull()!! + 1

        while (left + 1 < right) {
            val mid = (left + right) / 2
            when {
                count(mid) >= k -> right = mid
                else -> left = mid
            }
        }
        return when {
            count(left) == k -> left
            count(right) == k -> right
            else -> right
        }
    }
}
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