题解:P10240 [THUSC 2021] 搬东西
题目大意
给定一个长度为 \(n\) 的序列 \(a\) 和一个正整数 \(m\),现在按下述策略删除 \(a\) 中的数字:
选出一个下标序列 \(p\),使得其:
-
单调递增
-
\(\sum_{x\in p}a_x\leq m\)
-
元素个数最多
-
字典序是满足上述条件的序列中最大的
然后删除 \(a\) 中下标在 \(p\) 中的元素。问按上述策略进行几次删除会使 \(a\) 为空。
\(n\leq5\times10^4,m\leq10^9\)。
分析
如果没有第 4 条限制,那么只需要用 set 维护所有数字,然后贪心选择最小的元素即可。
如果有第 4 条限制,通过这样方法得到的元素个数也一定是最多的,因此一定选出的下标序列大小已经确定。
考虑从前往后确定该下标序列中的元素,对于当前位置,考虑二分,那么元素 \(id\) 能放在当前位置,当且仅当下标 \(\geq id\) 且还存在的元素中,最小的 \(k\) 个元素之和 \(\leq m\)。找到 \(id\) 之后,将 \(id\) 删掉,继续二分下一个元素。因此需要支持单点修改,考虑使用树套树维护这个东西,外层用树状数组或线段树维护下标区间,内层用权值线段树维护当前区间的元素的权值。
单点修改时,在 \(\log\) 个区间内同时修改。查询时,将询问拆为 \(\log\) 个区间,然后将这 \(\log\) 个区间的权值线段树合并进行查询。当然事实上你不需要合并,只需要同时维护 \(\log\) 个根节点,正常权值线段树找左子树大小时,就将这 \(\log\) 个根的左子树大小加起来即可。这是树套树的一种常见套路,全世界大概只有我一个不会。
总复杂度为 \(\mathcal{O}(n\log^3n)\)。

浙公网安备 33010602011771号