Chain Reaction

好题,介绍一下向上取整的整除分块

首先来看一下另一种做法吧

先看这篇文章

解释一下,再次需要操作的次数实际上就是还有多少个连续的正数的段,不难发现在攻击力为k的时候,像广搜一样操作x次后(指横着操作,而不是对着一个连续块一直操作),与操作一次攻击力为xk的操作是等价的,所以有最后的答案是ans0+ansk+ans2k+...

然后来解释一下我的做法,首先这道题目跟Chip and Ribbon这道题目非常像,都可以转化成积木大赛

那么这道题目怎么转化呢?首先对一个确定的k,将每个ai除以k并且向上取整,然后做出差分数组就好了,不难证明这是正确的

问题是怎么优化,实际上,我们使用转化对象法,不从k的角度考虑,而从每个数字的角度考虑,不难想到整除分块

但是这里是向上取整,我们不能简单的将蓝书上的推导,所有下取整符号换成上取整符号,小于等于号和大于等于号都取反来做,尽管这样的推导是正确的,但是最后分的段没有分完全。比如如果我们这么做了,那么每一段就是[g(x),x],然而有可能g(x)1处的值也与x的值相同

所以这样就会导致TLE,但是仍然有一个正确的结论:最多只能分成O(2k)段,因为仍然只有可能有这么多种取值

那么也就是说,我们仍然可以使用这样的算法:最开始令L=1,然后每次循环找到一个最大的R,使得nL=nR,之后再令L=R+1即可,如果能找到这样的R的话,我们的循环也是最多进行O(2k)次的

那么这个R怎么找呢?实际上,通过讨论n是否整除d,我们可以得到如下恒等式:nd=n+d1d,于是我们就可以将向上取整转化为向下取整,即每一次循环的时候,找最大的R使得n+L1L=n+R1R,也就是n1L=n1R,这就是我们熟悉的整除分块的形式了

那么现在时间复杂度正确了,怎么统计答案呢?实际上,我们发现答案只与差分数组有关,所以我们循环讨论每一个怪物,如果这个怪物的血量比前一个的高,那么这里的差分肯定为正数(反之为负数,处理方法一样,下面只讨论正数的情况),我们对这个怪物进行上面的循环,然后将答案数组(e.g.,ansk表示攻击力为k的时候的答案)的对应位置加上对应贡献,然后对上一个怪物进行同样的循环,然后将答案数组的对应位置减去对应贡献,最后在总的统计就好了

posted @   最爱丁珰  阅读(11)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示