1 条题解
-
0
题目大意
有 种玩偶,每种有价钱 、价值 和限购次数 。
给定 次询问,每次询问:- 删除一个玩偶
- 背包容量变为
- 求此时多重背包的最大价值
不同询问相互独立,即每次删除只针对当前询问。
问题分析
1. 直接方法的瓶颈
如果对每个询问重新计算多重背包:
- 单次多重背包: 或优化后
- 次询问:
- 数据范围:,,
- 直接计算不可行(约 操作)
核心思路:前后缀分解
1. 前后缀背包预处理
定义:
f_pre[i][j]:只使用前 个物品(编号 到 ),容量为 的最大价值f_suf[i][j]:只使用后 个物品(编号 到 ),容量为 的最大价值
这样预处理后,对于删除物品 的询问:
- 可用物品 = 前 个物品 + 后 个物品
- 答案 = $\max\limits_{0 \leq k \leq money} \{ f\_pre[del][k] + f\_suf[del+1][money-k] \}$
2. 多重背包优化
使用 单调队列优化 的多重背包:
- 对每个余数 ()分别处理
- 维护一个单调队列,保证队首是当前窗口的最大值
- 复杂度从 优化到
算法步骤
阶段 1:预处理前缀背包
- 初始化
f_pre[0][j] = 0 - 对于 到 :
- 先复制上一行的结果:
f_pre[i] = f_pre[i-1] - 对当前物品进行单调队列优化的多重背包更新
- 先复制上一行的结果:
阶段 2:预处理后缀背包
- 初始化
f_suf[n+1][j] = 0 - 对于 到 :
- 先复制下一行的结果:
f_suf[i] = f_suf[i+1] - 对当前物品进行单调队列优化的多重背包更新
- 先复制下一行的结果:
阶段 3:处理询问
对于每个询问 :
- 答案 = $\max\limits_{k=0}^{money} f\_pre[del][k] + f\_suf[del+2][money-k]$
- 注意下标调整:删除第 个物品(0-indexed)后,前 个物品对应
f_pre[del],后 个物品对应f_suf[del+2]
复杂度分析
-
预处理:
- 前缀背包:
- 后缀背包:
- 总计:
-
回答询问:
- 每个询问:(枚举容量分割)
- 总计:
-
总复杂度:
- 最坏:,可以接受
关键点
1. 单调队列优化多重背包
对于物品 :
- 按余数 分组处理
- 维护队列存容量下标,保证 单调递减
- 窗口大小:
2. 前后缀思想
- 将"删除一个元素"转化为"合并两个不包含该元素的背包"
- 避免重复计算,实现询问间共享信息
3. 下标处理
- 玩偶从 0 开始编号
f_pre[i]包含前 个玩偶(编号 0 到 )f_suf[i]包含后 个玩偶(编号 到 )
总结
这道题通过 前后缀预处理 + 单调队列优化,将原本 的暴力算法优化到 ,是处理"带删除的背包问题"的经典方法。核心在于利用预处理避免重复计算,以及使用单调队列高效处理多重背包。
- 1
信息
- ID
- 3861
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 4
- 已通过
- 1
- 上传者