题解:P10240 [THUSC 2021] 搬东西

题目大意

给定一个长度为 \(n\) 的序列 \(a\) 和一个正整数 \(m\),现在按下述策略删除 \(a\) 中的数字:

选出一个下标序列 \(p\),使得其:

  1. 单调递增

  2. \(\sum_{x\in p}a_x\leq m\)

  3. 元素个数最多

  4. 字典序是满足上述条件的序列中最大的

然后删除 \(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)\)

posted @ 2024-06-27 20:23  jxy2012  阅读(47)  评论(0)    收藏  举报
//雪花飘落效果