_JF_
2024-10-30 13:57:10
分块。这就是分块。记得同届的应该都是初一就会了吧。
自己还是很可笑。啥都不会。
分块其实是一种「思想」。就是字面意思,把整个序列按照一定长度,划分成若干个块,然后对于每个块我们去维护一些信息。
你可以认为这是一种优化的暴力。
这样的话,我们对每个块去整体考虑,这样的「整体」其实只有
P3203 [HNOI2010] 弹飞绵羊
这是分块思想的题目,注意到我们暴力跳肯定是不行的。我们考虑分块。
其实这题感觉转成树形结构是更好想的?
对于每个块,我们维护块内每个点跳出这个块的步数和位置,这个我们扫一遍就可以维护。
因为是单点修改,所以我们每次只用对一个块重构,这是
按照整体来看,我们最多跳
分块是较为灵活的,我们还是回到最简单的单点/区间加,区间/单点查询上面去。
P2357 守墓人
首先是预处理。我们要预处理块长(一般是
这个显然可以做到
对于每个块,我们需要维护块内所有数的和,记为
单点修改显然是容易的,我们找到点对应的块改
对于区间修改,我们需要用线段树的思想,维护一个
所以对于区间修改,我们遇到整块,直接打标记并修改
对于区间查询,我们遇到整块,直接查询
我们这样做时间复杂度显然是
如果你用线段树的角度去看的话,维护最值也是显然的。
这就是分块最基础的应用。注意实现的时候,
不妨把他和我们的普通暴力比较。
普通暴力相当于就是认为块长为
所以一般取
Loj 分块
经典的训练。启动!
T1,T4,T7 都是上面讲过的类似题。
T2,T3 是一类题,讲一下 T2,很经典。
我们对每个块维护一个 vector 表示当前块,块内数排序以后的状态。
要找块内小于
对于区间加,涉及到散块,我们就把那个块单独拎出来重构,对于整块而言,区间加不会改变相对大小关系,打标记即可。
分块体现出来的就是:把问题摊到若干块上去怎么去维护,因为一个块内数的数量只有
就像这里,维护排序后的状态。比较厉害。
T5:区间开方,区间求和。
这是一个结论题。我们对一个数开方,开个
所以每个块开方次数不超过
T8:区间查询等于
就是这个“同时”,太厉害了。
我好像只会一个
正解是,对于每个块,我们维护块内的数是否相同,如果不同,我们暴力统计,如果相同我们直接判断。
这样为什么能保证时间复杂度呢。因为一个块查询的次数
所以总的时间复杂度是
剩下两个题还没写。
P5309 [Ynoi2011] 初始化
第一道 Ynoi,谁知道
观察部分分,提示我们如果
这里不能用线段树等维护,因为还要带个
如果
不妨对固定的
容易观察到,对于每个块而言修改的位置
考虑查询的时候固定
那么对于
P10045 [CCPC 2023 北京市赛] 线段树
维护连乘?困难。应该是往推柿子的方法靠一靠。
考虑整块我们怎么做,不妨按照惯性想我们维护一个
比如说当前块是
简单展开,是
如果我用这样的方式表示,我们不难想到,展开式的每一项其实就是在一个
所以我们把当前块里面的数和加上的数(标记)分开考虑。假设我们写成下面这张图的形式;
红色
我们显然有,如果选了
我们专心考虑这个黑色部分。
好的,那么我们现在的一个子问题是,我要求在块内选
其实这里我在想的时候的做法要用除法,是假的, 这里直接讲正解,是递推。
考虑
显然有:
但是,注意到如果我们这样去重构块的话时间是
然后这里我也没观察出来,注意到加上的数都是偶数,即
所以这时候我们只用
那么注意你选了
这样才能保证
有:
具体的,这时候我们选的是
具体实现的时候
然后就正常分块就做完了。其实也不用卡常,加个快读就擦着过去了,懒。