1 条题解
-
0
「美团 CodeM 复赛」通信 题解
题目回顾
- 有 个信号塔,第 个塔的位置是 ,信号强度 (互不相同)。
- 有 个人,第 个人的位置是 ,向左走一格要 秒,向右走一格要 秒。
- 传递规则:当 有信息时,选择 (),令 ,然后 和 同时向 移动,都到达 后信息从 传给 ,两人瞬间回到原位置, 失去信息, 获得信息。
- 对每个 求信息传到 的最短时间 及方案数 (模 )。
- 。
- 输出 和 (分别用 64 位有符号、32 位无符号类型计算异或)。
一、数学模型化简
1. 确定
由于 互不相同,设 为 左边第一个满足 的位置(若不存在则 ,但方便起见可以设 并特判)。
对任意 :- 如果 ,则区间 的最大值位置 (因为 且 左边没有更大的跨过它)。
- 如果 ,则 ( 是 的最大值)。
2. 传递时间
记 。
情况 A:()
- 到 :距离 ,时间 。
- 到 : 在 左边,向右走 格,每格 秒,时间 。
- 总时间 。
情况 B:()
- 到 :向左走 格,每格 秒,时间 。
- 到 :向右走 格,每格 秒,时间 。
- 总时间 。
二、动态规划方程
设 为从 传到 的最短时间,显然 。
一次传递:从 传到 花费 ,然后从 传到 花费 。
$$f_i = \min_{1 \le j < i} \big[ f_j + T(i,j) \big]. $$
所以:代入 的分情况:
-
:。 令 ,则这部分最小值 = 。
-
:。
令 ,则- 若 ,则时间 = 。
- 若 ,则时间 = 。
所以这部分要分两段求最小值。
三、数据结构设计
观察:
- 对 的部分,需要支持区间 。
- 对 的部分,需要支持:
- 区间 求 (当 较大时)。
- 区间 求 (再加 )。
但 可能不是整数,且分界点会随 变化。
代码中的简化技巧
在给定代码中,使用了线段树维护两个值:
min_value[0]:存 (用于 的情况,但实际处理时是另一形式)。min_value[1]:存 ?
不,从代码awp.min_value[1] = dp[i] - 1LL * i * a看,这里 就是 ,所以它存的是 ?可能用于另一种对称情况。
实际上,因为 的表达式是对称的,可以用单调栈维护 ,并在栈变化时更新线段树的“偏移量”(
delta),使得查询能在 完成。
四、代码核心流程
- 读入 。
- 单调栈求 (左侧第一个 更大的位置)。
- 线段树
tree维护两个值:tree[id].min_value[0]:对应 (或者带偏移后的值)。tree[id].min_value[1]:对应 (或者带偏移后的值)。 以及对应的方案数cont[0]和cont[1]。
- 遍历 :
- 更新栈,并在栈弹出时更新线段树区间(
update操作,增减偏移量)。 - 查询(
query函数)得到两个候选最小值和方案数,合并得到 。 - 将 的信息插入线段树。
- 更新栈,并在栈弹出时更新线段树区间(
- 输出 和 。
五、时间复杂度
- 单调栈操作总 。
- 线段树每次更新或查询 。
- 总复杂度 ,可过 (常数较小)。
六、关键点总结
- 分类讨论 与 的位置关系,将 化简为较简单的形式。
- 将 表达式拆为分段函数,分别对应不同的 范围。
- 用单调栈维护 ,并借助线段树动态维护两类最小值查询,支持区间加偏移量。
- 方案数在求最小值时同时累加(模 )。
- 最终答案用异或输出。
示例对应(样例):
$$\begin{cases} f_1 = 0 & g_1 = 1 \\ f_2 = 3 & g_2 = 1 \\ f_3 = 13 & g_3 = 1 \\ f_4 = 9 & g_4 = 2 \\ f_5 = 12 & g_5 = 4 \\ f_6 = 13 & g_6 = 1 \end{cases} $$输出:
6 6
- 1
信息
- ID
- 6047
- 时间
- 3000ms
- 内存
- 2048MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者