倍增值域分块例题

这里引用一下 lxl 学长的 PPT 上的原话,来说明一下倍增值域分块的应用类型:
带
时间复杂度的均摊,可以分出两种常见的类型:
每个数被操作一次之后就会减半
每个数被操作一次之后可能减小的很少,操作很多次后减半
对于第一种问题,难点在于如何高效找到每次操作,有哪些数需要被减半
对于第二种问题,常见的解决方法是倍增值域分块
一般问题是
的 这种形式的问题适合用倍增值域分块解决 这个套路有一定技巧性,得结合具体问题具体分析
CF702F T-Shirts 2800
题目大意
有
有
问最后每个人买了多少件 T 恤?如果有多个
解答
这是倍增值域分块的板子题。
首先可以把
然后我们每次做修改操作(所有能减少
这样的话,因为是值域
加上每一次分裂、合并的复杂度为
P7447 YNOI rgxsxrs AT Lv.17
题目大意
给定一个长为
1 l r x
:表示将区间
2 l r
:表示询问区间
解答
这里依然使用倍增值域分块的 trick。
首先,我们这里设定使用 2 进制。那么就把整个序列分为
我们对于每一个区间
然后修改了之后我们会发现有一些数它已经不属于原本的区间里了。我们可以暴力倒序遍历所有区间,while
判断是否有数小于
查询就遍历区间,累加
因为每一个数最多会被暴力弹出、加入
但是!这道题最重要的一点就是它卡空间,空间 64MB,就相当于是必须线性!
于是我们就可以利用一个新的 trick:底层分块。也就是,对于每一个线段树叶子节点,它的父亲对于的范围
块长为
不过这样会被卡时。只需要把设定从 2 进制改成 32 进制就可以了。
P9069 YNOI TEST_98 AT Lv.16
题目大意
给定一个长为
- 给定
,对于所有 满足 且 , 。 - 给定
,求对于所有 满足 且 , 的和。
解答
成功拿下全机房首杀!
只不过调了一个晚上 + 一个上午o(TヘTo)
和前面那道题思路类似,依然是倍增值域分块(或加上底层分块,这道题不卡空间,所以写不写均可)。
然后因为
但是,这道题要注意的是,我那个调了一天的点,就是 change
操作的时候要剪枝!
1 | void change(int x, int l, int r, int ql, int qr, ll val){ |
P8522 IOI2021 Dungeons AT Lv.16
题目大意
这是一道交互题,你只需要实现代码中要求的函数。
你的代码不需要引用任何额外的头文件,也不需要实现 main
函数。
Robert 正在设计一款新的电脑游戏。游戏中有一位英雄、
英雄一开始进入地牢
如果英雄的能力值大于等于敌人
否则英雄会战败,这使得英雄的能力值增加
注意
当英雄进入地牢
Robert 希望你通过
你要实现以下函数:
1 | void init(int n, int[] s, int[] p, int[] w, int[] l) |
:敌人的数量。 、 、 、 :长度为 的序列。对于每一个 ( ): 是敌人 的能力值,也是击败敌人 后英雄增加的能力值。 是英雄被敌人 击败后增加的能力值。 是英雄击败敌人 后进入的下一个地牢的编号。 是英雄被敌人 击败后进入的下一个地牢的编号。
- 恰好调用此函数一次,且发生在任何对如下的 simulate 函数的调用之前。
1
int64 simulate(int x, int z)
:英雄的起始地牢编号。 :英雄的初始能力值。 - 假设英雄的起始地牢编号为
,初始能力值为 ,函数的返回值是相应情况下游戏结束时英雄的能力值。 - 恰好调用此函数
次。
对于所有数据:
(对于所有的 ) (对于所有的 ) (对于所有的 )
解答
我们可以给值域分块。先以
我们处理当现在的能力值
我们预处理
这时为了确定它到底是跳
然后为了更新能力值,我们设
这三个数组都可以在 init
操作时预处理。
然后就是 simulation
函数。这里就枚举,当现在的
- Title: 倍增值域分块例题
- Author: 11490DX
- Created at : 2025-03-07 17:54:46
- Updated at : 2025-03-07 21:03:04
- Link: https://11490dx.net/2025/03/07/ds-bilf-val-deco/
- License: This work is licensed under CC BY-NC-SA 4.0.