题目理解
给定一个长度为 n 的数组 arr,初始只有下标 p 处为 1,其余为 0。同时给出一个 banned 列表,这些位置永远不能变成 1,且保证 banned[i] != p。你可以任意翻转长度为 k 的连续子数组(即逆序整个子数组)。对每个位置 i,求最少翻转多少次能让 arr[i] 变成 1,如果不可行则返回 -1。
翻转操作:把
[L, R]区间内的元素顺序完全颠倒。
显然 p 本身不需要翻转,所以 ans[p] = 0。其他位置需要借助已经变成 1 的位置逐步'传播'过去。这听起来很像 BFS —— 从已知的 1 出发,每翻转一次相当于走一条边权为 1 的边,到达新的下标。
翻转后的下标规律
对于区间 [L, R],翻转前后对应位置满足:
- 原来在
L的元素会跑到R - 原来在
L+1的元素跑到R-1 - ...
- 一般地,原来下标
i会去到j = L + R - i
如果我们固定 i,那么 j 的取值由 L 和 R 决定。但 L 和 R 只能以步长 1 左右滑动,所以 L+R 的变化是以 2 为公差的等差数列。也就是说,从 i 出发,经过一次翻转能到达的所有 j 构成一个公差为 2 的等差数列,且所有可达下标要么全是奇数,要么全是偶数(取决于 i 的奇偶性)。
可达范围
对于给定的 i,j 能取的最小值和最大值受到数组边界和子数组长度 k 的限制。
- 如果
i刚好是子数组的右端点,那么j = i - k + 1,这是理论上的最小值。 - 如果
i刚好是子数组的左端点,那么j = i + k - 1,这是理论上的最大值。
但是当 i 靠近数组两端时,它无法成为端点。例如 i < k-1 时,根本不存在以 i 为右端点且长度为 k 的子数组;同样 i > n-k 时,i 无法成为左端点。此时需要对边界进行修正:
- 若
i < k-1,最左端的子数组是[0, k-1],此时j = k - 1 - i。 - 若
i > n-k,最右端的子数组是[n-k, n-1],此时j = 2n - k - i - 1。
综合起来,i 经过一次翻转可达的 j 的范围是:
j_min = max(i - k + 1, k - 1 - i)
j_max = min( + k - , *n - k - - )


