【学习笔记】倍增分块

倍增分块常用于处理数值递减/递增的问题,形如当 aix 时,使 aiaix

分成 [2k,2k+1) 的若干块。

P4587

题目链接

暴力就是排个序,然后便利值域,依次加入。加入完 i 时,遍历到值域第一个不能被组成的位置 x[1,x) 的数都是可以被已经加入的数组成的,所以 ai+1 一定不能大于 x。一旦大于 xx 这个位置就不能被表示了。那么 ai+1x,加入 ai+1 会使得下一个不能被组成的位置是 x+ai+1。找到第一个不行的就行。

考虑优化这个过程,注意到 x 是单增的,所以用倍增分块。设当前在 x[2k,2k+1),那么要往后加数,下一个数必然不能大于 x。所以可以查询 [2k,2k+1) 的最小值,如果最小值小于等于 x,那么由于最小值 ai2k,x2k,所以 x+ai2k+1,那么这一块的所有数必定可以取走,所以就取走 [2k,2k+1) 所有数加到 x 里面。每个块预处理用个 st 表就行,复杂度 Θ(n(logn+logV))

CF1515I

出现了形如 cwiccwi。考虑按要求排序,然后模拟这个过程,发现有时候会遇到一个比 c 大的数取不了跳过,很难受。那么可以考虑特殊处理这些,设当前 c[2k,2k+1),那么只要取到一个在 [2k,2k+1) 的数必然就会降级为至多 [2k1,2k)。所以关注那些 <2k 的数,如果这个都取到某个数都不能取了,那么那时候肯定是 c<2k

那么该怎么找到这样一个数呢,考虑在线段树上维护所有 <2k 的重量和 sumk,那么可以线段树二分找到第一个 sumk>c 的位置,这是第二种情况。再考虑第一种,显然 c 要大于这个 2k 的重量和之前所有 <2k 的重量和,设这两者的和是 t,那么 c 还得小于之前所有 2k 物品的那些 t 值,可以用线段树二分求出。

所以每次 logn,做最多 logV 次,复杂度单次是 Θ(nlognlogV)

本文作者:FantasyNumber

本文链接:https://www.cnblogs.com/MiniLong/p/18297265

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   FantasyNumber  阅读(119)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
💬
评论
📌
收藏
💗
关注
👍
推荐
🚀
回顶
收起