2025.06.19 CW 模拟赛 B. 黄金星球

B. 黄金星球

题目描述

小 Y 很穷,于是他决定开飞船去寻宝。在历经千辛万苦后,他终于来到了一个遍地黄金的星球!尤为吸引人的是,在小 Y 面前有 \(n\) 块金子排成一列,每块金子有个重量,小 Y 可以选择一段区间内的金子用最大载重量为 \(w\) 的飞船运走,也就是说,运走的金子重量之和不能超过 \(w\)。可是见财眼开的小 Y 哪里管这些,贪心的他直接把所有 \(n\) 块金子运上了飞船。结果飞船起飞 5 秒后船毁人亡……

"啊啊啊啊……"小 Y 吓醒,原来这只是他的白日梦。醒来后的小 Y 认为这个梦很有研究价值,它决定问你 \(m\) 个问题,每个问题形如,若小 Y 被限制只能拿 \([l_i, r_i]\) 内的金子,在最大载重量为 \(w_i\) 的飞船安全起飞的前提下,他一次能运走的金子的总重量最大为多少。


思路

我们发现 \(n \leq 2000\),所有子区间是可枚举的,而我们要找的就是子区间,所以不妨把它们全都作为元素搞出来。然后还要限制子区间被框在一个大区间 \([1, r]\) 内,那么可以套路的用扫描线处理,把询问存在 \(r\) 处,离线自左而右地在右端点处理子区间和询问,这样保证了所有子区间都在每个询问的 \(r\) 左侧。

对每个询问我们二分答案,看在所有和 \(\geq ans\) 的子区间中,是否有左端点 \(\geq l\) 的,就是找最大值。于是我们预先将所有子区间按和从小到大排序,线段树维护区间内的子区间的最大的左端点即可。时间复杂度 \(\mathcal{O}(n^2 \log n + q \log^2 n)\)

以上为题解做法, 接下来讲一下 zcy 的做法.

我们考虑将询问全部离线并按照 \(w_i\) 升序排序. 现在假设有一个数据结构, 可以支持我们每次枚举一个排序后的询问 \((l_i, r_i, w_i)\), 我们就将所有的权值在 \((w_{i - 1}, w_i]\) 范围内的三元组 \((\)左, 右端点以及权值\()\) 插入进来. 同时需要在合理的复杂度内求出左右端点 \([l_i, r_i]\) 中权值 \(\le w_i\) 的最大权值, 即所求答案.

一般来说, 这是一个二维偏序问题, 需要使用树套树或 \(\rm{CDQ}\) 分治解决. 不过在这道题中, 由于 \(0 \le x_i \le 10^{18}\), 若限制权值 \(\le k\), 固定 \(r\), 记 \(l_\min\) 为最左侧的一个端点使得 \(sum_{l_\min, r} \le k\). 不难发现在 \(r\) 增大的过程中, \(l_\min\) 是单调不降的, 这启发我们可以使用二分.

假设当前询问为 \((l_i, r_i, w_i)\). 具体而言, 我们使用线段树, 将其每个叶子结点作为区间右端点存储权值 \(\le w_i\) 的最靠左的左端点, 相当于一个二元组 \((L, val)\), 分别为左端点以及权值, 正常向上合并即可. 在查询时, 我们找到区间 \([l_i, r_i]\) 中最靠左的 \(L \ge l_i\)\((L, val)\) 的位置 \(p\), 由于 \(L\) 是单调的, 所以其右侧所有二元组中的 \(L\)\(\ge l_i\), 可以使用线段树上二分做到单 \(\log\). 对于 \(p \sim r_i\) 的节点, 直接区间查 \(\max\) 即可, 而对于 \([l_i, p)\) 的节点, 它们的 \(L < l_i\), 我们需要将左端点限制到 \(l_i\), 此时根据贪心, 右端点取到 \(p - 1\) 是合法且最优的.

复杂度 \(\mathcal{O}(n^2 \log n + q \log n)\).

posted @ 2025-06-19 20:49  Steven1013  阅读(13)  评论(0)    收藏  举报