莫队总结

本文深入讲解了莫队算法,一种高效的区间查询算法。通过详细解释无修改普通莫队的实现原理,包括分块、排序和更新操作,以及如何在特定条件下达到O(n sqrt(n))的时间复杂度。并提供了几道经典练习题及其代码链接。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

莫队总结

标签: 算法——莫队
阅读体验: https://www.zybuluo.com/Junlier/note/1283909
我学的时候 大米饼的莫队
既然学了这个神奇的东西,那我就来简单地总结一下

闲话要听

首先放一个例题: luogu 小B的询问
其实就是小z的袜子的弱化版。。。虽然网上都拿小z的袜子作模板讲,但是还得小小推个式子我当时学的时候就比较烦。。。
行吧,这两题的核心部分是一模一样的,你会发现小B的询问的答案就是小z的袜子的答案的分子。。。

无修改普通莫队

行吧我们入正题了
我现在说的莫队都只是无修改的莫队啊。。。
不需要觉得这个东西很难,虽然它并不简单。。。

前置

  • 想学莫队你首先得了解分块,不会出门左转度娘
  • 使用莫队需要满足以下条件:
  1. 区间查询问题且可以离线(当然不带修改)
  2. 可以根据\((l,r)\)的答案推出\((l-1,r),(l,r-1),(l+1,r),(l+1,r+1)\)
    例如上面的例题:(拿\((l,r)到(l-1,r)\)来讲)

    • 维护一个\(sum[]\)数组表示每个数在当前询问区间的出现次数,\(v[i]\)表示\(i\)位置上的数
      那么 $ Ans=\sum_1^K sum[i] $
    • 所以每次Update的时候可以做到\(O(1)\)完成
      1. \(Ans\)减去\(sum[v[l-1]]^2\)
      2. \(sum[v[l-1]]\)减少一个
      3. \(Ans\)加上\(sum[v[l-1]]^2\)

实现

  1. 对被操作序列分块(先理解为按$ \sqrt n$分块吧)(先记下来,别问为什么!)
  2. 把所有的询问记录下来,按左端点排序,若左端点相同则按右端点排序
    注意,这里不是直接排序,我们把左端点是否相同定义为是否在同一个块内
    也就是说: 左端点按它所在块的编号排序,若两个左端点在同一个块内,则按右端点排序
  3. \(O(m)\)枚举询问,做完了。。。(你暂时当我放屁)

解释一下为什么

不用多说,一切的一切都是为了保证复杂度,所以我们来推一下时间复杂度

  1. 首先最外层肯定得枚举\(m\)个询问(已经排好序),我们用\(l,r\)指针代表当前询问所在区间
  2. 看一下\(l\)的移动复杂度:
    - \(l\)在同一个块内移动:每个询问最多\(\sqrt n\)
    - \(l\)不在同一个块内移动: 每个询问最多\(2\sqrt n\)
    总的来说就是\(m\sqrt n\)
  3. 然后是\(r\)的移动复杂度:
    - 对于每一个块,r最多移动n次,我们又有\(\sqrt n\)个块
    那么复杂度是\(n\sqrt n\)
  4. n和m的数量级一般差不多,所以整个莫队的复杂度就是\(n\sqrt n\)滴辣

总结

怎么拓展上面也说了,怎么操作也就这样了,相信你依旧是懵的对不对,那我再总结一下

  1. 分块 对后面的作用可以往上再看一下
  2. 排序 对于所有询问我们做了排序,是为了保证我们的答案跟着询问拓展时的复杂度正确
  3. \(O(1)\)地实现拓展 这个上面我应该讲的比较清楚了吧(当然每道题不同)

那么应该还是比较清晰了吧
几道题目练练手
luogu 小B的询问 我的code
luogu 小Z的袜子 我的code
luogu 异或序列 我的code

带修改莫队

笔者表示自己还没学,抱歉

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值