首页 > 其他分享 >普通莫队学习笔记

普通莫队学习笔记

时间:2022-11-27 20:34:27浏览次数:60  
标签:dfrac 询问 个数 笔记 普通 莫队 复杂度 block

莫队算法主要用于可以离线的区间询问回答。

引子

考虑一个这样的问题:假设没有事先求前缀和,你知道了数组第 \(5\) 个数到第 \(100\) 个数的和,现在询问问你第 \(4\) 个数到第 \(102\) 个数的和。怎么快速的计算?

显然直接暴力的去把第 \(4\) 个数加进去,然后把第 \(101\) 个数和 \(102\) 个数加进去。也就是说,当我们连续询问了两个问题,且这两个问题的交集比较大的时候,我们直接暴力的去处理不相交的部分,其实时间复杂度是很优秀的。

莫队就是这样一种处理询问的方式,通过排序,使得两两询问之间的交集尽可能的大。

如何排序

字母 含义
\(L\) 某一询问的左端点
\(R\) 某一询问的右端点
\(block\) 块长
\(N\) 数字个数
\(M\) 询问规模

如何排序使得区间交集尽可能大?

根据分块的思想,莫队按照 \(\dfrac{L}{block}\)(设块长为 \(block\))进行分组,然后每一组中的区间再按照 \(R\) 从小到大排序。

因为 \(L\) 被分了组,所以 \(L\) 端点移动复杂度不大于 \(block\)。

对于相同组, \(R\) 从小到大移动不超过 \(N\)。因为总共有 \(\dfrac{N}{block}\) 组, 所以总复杂度不超过 \(\dfrac{N^2}{block}\) ,均摊到每一次询问上就是 \(\dfrac{N^2 \times block}{M}\)。

当 \(N\) 和 \(M\) 是一个数量级时,每次询问均摊的复杂度就是 \(block + \dfrac{N}{block}\)。当 \(block\) 取 \(\sqrt{L}\) 时,复杂度达到最小值,为 \(O(n\sqrt{n})\)。

code

一次排序 + 四遍 \(while\) 循环即可

注意 \(l\), \(r\) 移动区间时,++l--l++r--r 的顺序排列仅有 \(3\) 种排列是正确的,如下图(图源 OI-Wiki
img

口诀:先加后减,先左后右,先小后大

int n, block
struct query {
    int l, r, id;
    bool operator<(query x) {
        return l / block == x.l / block ? (r == x.r ? 0 : ((l / block) & 1) ^ (r < x.r)) : l < x.l;
    }
} q[N];

// update nowans
void move() {
    //...
}

void mo() {
    block = int(ceil(pow(n, 0.5)));
    sort(q + 1, q + n + 1);
    for (int i = 1; i <= n; ++i) {
        query Q = q[i];
        while (l < q.l) move(l++, 1);
        while (l > q.l) move(--l, 1);
        while (r < q.r) move(++r, 1);
        while (r > q.r) move(--r, 1);
    }
}

应用

区间 \(mex\)

首先莫队把询问离线排序后,我们可以很简单的维护出一个桶。

每次暴力维护移动的时候,就令 \(num[\) \([\) \(l\) \(]\) \(]\) 加加或者减减。问题在于如何快速求 \(mex\)。在四个循环跑完以后,我们已经知道了当前区间形成的桶,怎样快速求出 \(mex\) 呢?

考虑对于桶进行分块。每 \(block\) 个桶合并出一个大的桶。这个桶存一下当前这个块内有多少元素被覆盖。

维护好这个大的桶后,我们就可以在 \(block + \dfrac{N}{block}\) 时间复杂度内求得区间 \(mex\)。

标签:dfrac,询问,个数,笔记,普通,莫队,复杂度,block
From: https://www.cnblogs.com/ckb2008/p/mo-note.html

相关文章

  • 学习笔记-Django框架的使用
    前言:本博客为技术小白的记录学习过程,有错误或不解的地方请指出!!!一.安装和创建项目1.安装1.1命令行下载pip3installdjango==1.11.11 (可以跟镜像地址:-i+镜像地址......
  • Spring Boot笔记(全)
    前言serverlet服务器端小程序,第一代javaweb开发技术,基于java实现了一套用于动态网站的APITomcat\Jetty\Undertow都是Servelet容器,用来管理Servelet类jsp在html页......
  • 20221127 英语笔记
    Word\(\textsf{tent}n.\)帐篷\(\textsf{notice}n.\)布告\(\textsf{recently}adv.\)近期\(\left\{\begin{array}{ll}\textsf{accept}&\textsf{主观意义下(你......
  • typescript笔记
    letu:undefined=undefinedletn:null=null类型注解functiongreeter(person:string){return'Hello,'+person}letuser=[0,1,2]console.log(gre......
  • TypeScript学习笔记-06 类、构造器、继承、super
    //使用类来定义一个类classPerson{//readonly开头的表示只读的属性,无法进行修改//定义实例属性readonlyname:string='索隆';//静态属性......
  • Eclipse和MyEclipse安装和使用git(egit)图解笔记
    Eclipse、MyEclipse使用git插件(egit)图解在开发Java、JavaEE等相关程序时,我们会用到Eclipse或者MyEclipse,同时使用到git作为版本控制软件,所以我们需要在这些IDE上集成git插......
  • 【一些自救】没有什么用的神经网络学习笔记(还没写完)
    即将面临例训而什么也不会的菜鸡惊恐看书发现看到下一章忘记上一章,于是写点笔记拯救什么也不会的自己或许能对你有些帮助,如果没有,这太正常了,忽略它吧 神经网络与卷积......
  • 宝宝精刷题笔记 面试题 02.05. 链表求和
    题目描述给定两个用链表表示的整数,每个节点包含一个数位。这些数位是反向存放的,也就是个位排在链表首部。编写函数对这两个整数求和,并用链表形式返回结果。示例1:输入......
  • 《vue.js设计与实现》笔记(1~4章)
    以下内容均来自本书第1章命令式编程与声明式编程关注结果(声明式)和关注过程(命令式)运行时和编译时(vue、react、svelte)坐火车时,进站检票(编译时)和上车检票(运行时)框架性......
  • 读书笔记——《雾都孤儿》
    摘要:这篇笔记是记录关于我正在阅读的《雾都孤儿》,在这里我将会记录阅读时的感想感悟与好句摘抄,同时可能会写一些小随笔,读书或者阅读是一条漫长的路,在路上可能会遇到很多的......