把环从任意位置切成若干连续段,每段都要凑齐全部 m 种宝石,求最多能切多少段。
nxt[i]=从 i 开始最短能凑齐 m 种后的下一个起点;③倍增统计:枚举起点 i,沿 nxt 尽量多跳,落点不超过 i+n 的段数最大值即答案。课堂安排:先理解“每段尽量短才能切更多”,再讲 nxt 的双指针,最后用倍增把“一段段跳”从 O(n) 加速到 O(log n)。
nxt[i] 就是“从 i 出发的最短合法段”的下一个起点。curr,只要 curr ≤ i+n,把剩下的零头并进最后一段(它仍含全部 m 种),就是一个合法的 k 段划分。所以条件是 nxt^k(i) ≤ i+n,用倍增求最大 k。因为整条项链本身就含全部 m 种,所以每个起点至少能切出 1 段,答案 ≥ 1。
破环成链后位置 1..12(后 6 个是复制)。选一个起点,沿 nxt 跳段,落点不超过 起点+6。
Q1. 为什么每段都取“最短的合法段”最优?
Q2. 处理“环”最常用的技巧是?
Q3. nxt[i] 可能等于 2n+1。若忘了给 f[2n+1][0] 设哨兵会怎样?
| 跳第几段 | 当前起点 curr | nxt[curr] | ≤ i+n=7 ? | 累计段数 |
|---|---|---|---|---|
| 1 | 1 | 3 | 是 | 1 |
| 2 | 3 | 5 | 是 | 2 |
| 3 | 5 | 7 | 是 (=7) | 3 |
| 停 | 7 | 9 | 否 (>7) | 3 |
nxt[i] 可能 = 2n+1(一段恰好用到最后一颗)。必须 f[2n+1][0]=f[2n+2][0]=2n+2,否则倍增跳进 0 号下标、段数爆炸(样例 1 会输出 262143 而不是 3)。r 不回退,整体 O(n);②倍增表 f[i][k] = 从 i 连跳 2^k 段后的起点;③查询时从高位到低位试跳,落点 ≤ i+n 才接受。复杂度:双指针 O(n),倍增 O(n log n);空间 O(n log n)。迁移:P2680 运输计划(倍增+树上差分)、P1083 借教室(区间差分)。