快到毕业季了,小度的班级组织大家拍毕业照。 小度的班级一共有n名同学,第i名同学学号为i ,身高为hi。 一张符合要求的毕业照最多包含k排,且需要符合以下要求: 1.每一排内的同学的学号从小到大排序后依次+1,也就是说,如果这一排的同学中最小的学号是x,则这一排内的同学们的学号从小到大依次是x+1, x+2,… 2.每一排内最高的同学和最低的同学身高差距不大于 d 。 3.第i+1(1≤i<k)排的同学中最小的学号恰好是第i排的同学中最大的学号+1 。
现在小度有三个问题请你回答: 1.假设只给定k,如果想要一张照片容纳所有同学,最小的 d是多少?
2.假设只给定 d ,如果想要一张照片容纳所有的同学,最小的k是多少?
3.假设给定k, d ,如果只拍一张照片,最多可以容纳多少位同学?
输入格式:第1行3个整数n,k, d (1≤k≤n≤5×1e5,1≤d≤1e9),表 示班级里的人数,和询问的两个参数; 第2行n个整数h1, h2,·…· ,hn (1 ≤hi≤1e9),表示每位同学的身高。 输出格式:输出3行,每行一个整数,代表对应问题的答案。
算法基础:二分|三分
为了回答小度的三个问题,我们需要分别考虑不同的约束条件,并使用适当的算法来求解。以下是详细的解题思路和算法实现。
我们需要找到一个最小的 d,使得可以将所有同学分成 k 排,每排的同学学号连续且身高差不超过 d。我们可以使用二分查找来解决这个问题。
我们需要找到一个最小的 k,使得可以将所有同学分成 k 排,每排的同学学号连续且身高差不超过 d。我们可以使用二分查找来解决这个问题。
我们需要找到在给定 k 和 d 的情况下,最多可以容纳多少位同学。我们可以使用滑动窗口来解决这个问题。
def solve(n, k, d, heights):
# 问题1:最小的 d 是多少?
def can_divide_with_d(d):
count = 1
min_height = max_height = heights[0]
for i in range(1, n):
min_height = min(min_height, heights[i])
max_height = max(max_height, heights[i])
if max_height - min_height > d:
count += 1
min_height = max_height = heights[i]
return count <= k
left, right = 0, max(heights) - min(heights)
while left < right:
mid = (left + right) // 2
if can_divide_with_d(mid):
right = mid
else:
left = mid + 1
min_d = left
# 问题2:最小的 k 是多少?
def can_divide_with_k(k):
count = 1
min_height = max_height = heights[0]
for i in range(1, n):
min_height = min(min_height, heights[i])
max_height = max(max_height, heights[i])
if max_height - min_height > d:
count += 1
min_height = max_height = heights[i]
return count <= k
left, right = 1, n
while left < right:
mid = (left + right) // 2
if can_divide_with_k(mid):
right = mid
else:
left = mid + 1
min_k = left
# 问题3:最多可以容纳多少位同学?
max_students = 0
dp = [0] * (n + 1)
for i in range(1, n + 1):
min_height = max_height = heights[i - 1]
for j in range(i, 0, -1):
min_height = min(min_height, heights[j - 1])
max_height = max(max_height, heights[j - 1])
if max_height - min_height > d:
break
dp[i] = max(dp[i], dp[j - 1] + (i - j + 1))
max_students = max(max_students, dp[i])
return min_d, min_k, max_students
# 输入
n, k, d = map(int, input().split())
heights = list(map(int, input().split()))
# 解决问题
min_d, min_k, max_students = solve(n, k, d, heights)
# 输出
print(min_d)
print(min_k)
print(max_students)
can_divide_with_d
函数用于验证当前的 d 是否可以将所有同学分成 k 排。can_divide_with_k
函数用于验证当前的 k 是否可以将所有同学分成 k 排。dp
数组用于记录每个位置可以容纳的最大同学数。通过上述方法,我们可以高效地解决这三个问题。