1478. 安排邮筒
考点
- 划分DP
- 前缀和
- 中位数
- 数学
题解
1 | class Solution { |
思路
每个邮箱负责的房子下标集合是一个连续区间,这是本题最大的难点
假设按数轴分布如下,小写字母是房子,大写字母是邮箱
1 | 1 2 x 3 4 y 5 z 6 7 |
很显然,12到x的距离肯定小于到y的,那么[1, 2]肯定在一个区间内
至于3,可以变成[1, 2, 3]为x所处理,也可以组成[3, 4]为y所处理,因为3到z的距离肯定大于到y的
总而言之,
最优方案中,我们可以认为有 \(k\) 个区间: \[ [l_1, r_1], [l_2, r_2], \dots, [l_k, r_k] \] 满足 \[ 1 = l_1 \le r_1 < l_2 \le r_2 < \dots < l_k \le r_k = n \] 第 \(j\) 个区间的房子由第 \(j\) 个邮箱负责。
假设我们已经确定了一个区间 \([l, r]\),对应的房子位置是: \[ h_l \le h_{l+1} \le \dots \le h_r \] 我们要在数轴上选一个点 \(p\),使得代价 \[ F(p) = \sum_{i=l}^r |h_i - p| \] 最小。
这是一个经典问题:绝对值和在一维上的最优解是中位数,直接背下来就好,这是数学性质
而对于代价,我们需要预处理 \[ cost[l][r] = \sum_{i=l}^r |h_i - h_{mid}| \] 其中 \[ mid = \left\lfloor \frac{l + r}{2} \right\rfloor \] 最朴素的做法:三重循环,直接对每个 \((l, r)\) 再扫一遍求和,时间复杂度 \(O(n^3)\),在本题 \(n \le 100\) 也能过,但可以更优。
用前缀和可以把计算 cost[l][r] 降到 \(O(1)\),总复杂度 \(O(n^2)\)。
令 \[ pre[i] = \sum_{t=1}^i h_t,\quad pre[0] = 0 \] 对于任意 \(1 \le a \le b \le n\), \[ \sum_{t=a}^b h_t = pre[b] - pre[a-1] \] 然后代价拆成左右两部分
对区间 \([l, r]\),中位数下标 \(mid\),对应值 \(h_{mid}\)。把区间拆成左半和右半:
- 左半:\([l, mid-1]\),这里所有点都在中位数左边
- 右半:\([mid+1, r]\),这里所有点都在中位数右边 中位数自己距离是 0,可以忽略
于是: \[ cost[l][r] = \sum_{i=l}^r |h_i - h_{mid}| = \sum_{i=l}^{mid-1} (h_{mid} - h_i) + \sum_{i=mid+1}^r (h_i - h_{mid}) \] 分别处理两块。
对于左半部分 \[
\sum_{i=l}^{mid-1} (h_{mid} - h_i)
= (mid - l) \cdot h_{mid} - \sum_{i=l}^{mid-1} h_i
\] 注意左半的数量是 mid - l 个(不包括
mid 自己)。 其中 \[
\sum_{i=l}^{mid-1} h_i = pre[mid-1] - pre[l-1]
\] 所以左边部分为: \[
left = (mid - l) \cdot h_{mid} - (pre[mid-1] - pre[l-1])
\] 对于右半部分 \[
\sum_{i=mid+1}^{r} (h_i - h_{mid})
= \sum_{i=mid+1}^{r} h_i - (r - mid)\cdot h_{mid}
\] 其中 \[
\sum_{i=mid+1}^{r} h_i = pre[r] - pre[mid]
\] 所以右边部分为: \[
right = (pre[r] - pre[mid]) - (r - mid)\cdot h_{mid}
\] 最后合并,于是: \[
cost[l][r]
= left + right
= (mid - l) \cdot h_{mid} - (pre[mid-1] - pre[l-1])
+ (pre[r] - pre[mid]) - (r - mid)\cdot h_{mid}
\]