这个坑终于填了…
上文接这里

莫队算法


这就是莫队(确信)

先放个可离线的题:

可离线:给你个序列,m次询问(可离线)一段区间有多少个不同的数(可离线)(数据范围 105 10 5 10^5)可离线

相信各位都已经拿高效的DS秒掉了

相信大家看完题目第一感觉就是离线(
考虑两次询问区间 (l,r) ( l , r ) (l,r)和 (l′,r′) ( l ′ , r ′ ) (l',r'),假设我们已经处理出 (l,r) ( l , r ) (l,r)区间内的答案,考虑将其拓展到 (l′,r′) ( l ′ , r ′ ) (l',r')

也就是要将左端点从 l l l移动到l′" role="presentation">l′l′l',右端点从 r r r移动到r′" role="presentation">r′r′r',一个数一个数的移动,复杂度就是 O(|l′−l|+|r′−r|) O ( | l ′ − l | + | r ′ − r | ) O(|l'-l|+|r'-r|)

对于每个询问用这种方法拓展到下一个询问,就可以求出所有的答案啦!
(这**不就是暴力吗(╯`□′)╯┴—┴

上面的做法随便想想都是 O(n2) O ( n 2 ) O(n^2)的…
那该怎么办(傻*博主举报了

莫队的小核心:

对询问离线,将区间分为 n−−√ n \sqrt n块,将询问以
1.左端点在同一块中的,按右端点排序;
2.左端点不在同一块中的,按左端点所在块排序;

之后再进行刚才说的暴力,复杂度就变成 n1.5 n 1.5 n^{1.5}的啦!

复杂度证明:

1.左端点在同一块中的询问:
一个块中最多有 n n n个询问,每次左端点最多移动n" role="presentation">n−−√n\sqrt n次,右端点一共移动最多 n n n次(因为右端点已经从小到大排好序),所以复杂度O(n1.5)" role="presentation">O(n1.5)O(n1.5)O(n^{1.5})(就是左端点移动的总复杂度)
2.左端点不再同一块中的询问:
最多跨 n−−√ n \sqrt n块,每次跨越左端点最多移动 n−−√ n \sqrt n次,右端点最多移动 n n n次,所以总复杂度n1.5" role="presentation">n1.5n1.5n^{1.5}
包含1,2两种情况的证明类似,复杂度一样 n1.5 n 1.5 n^{1.5}

(说了这么多,我选择nlogn的DS

莫队使用条件:

0.能用莫队过
1.能将询问离线
2.可以往外拓展收缩

说了这么多,回到刚才的小例题,直接看代码吧

#include<algorithm>
#include<ctype.h>
#include<cstdio>
#include<cmath>
#define N 200050
using namespace std;
inline int read(){int x=0,f=1;char c;do c=getchar(),f=c=='-'?-1:f; while(!isdigit(c));do x=(x<<3)+(x<<1)+c-'0',c=getchar(); while(isdigit(c));return x*f;
}
int n,m,Block_size;
int block[N],a[N],ans[N],l=1,r;///l=1,r=0代表初始状态(空区间)
int cnt[1000050],tmp;
struct Query{int l,r,id;
}q[N];///问题
inline bool cmp(Query a,Query b){return block[a.l]==block[b.l]?a.r<b.r:block[a.l]<block[b.l];///排序,同一块内按右端点排,否则按块排
}
inline void Update(int x,int k){///cnt[i]代表i颜色在区间出现的次数,k=-1代表删除,k=1代表插入if(!cnt[x]) tmp++;///如果开始没这个数字,这次操作会使这个数字出现,那么数字数(tmp)+1cnt[x]+=k;if(!cnt[x]) tmp--;///如果操作导致这个数字变没了,就要-1
}
int main(){n=read();///区间长度Block_size=sqrt(n);///分块for(int i=1;i<=n;i++){a[i]=read();///读入区间block[i]=(i-1)/Block_size+1;///每个位置属于哪块}m=read();for(int i=1;i<=m;i++){q[i].l=read();q[i].r=read();q[i].id=i;///读入询问}sort(q+1,q+m+1,cmp);///对询问排序for(int i=1;i<=m;i++){while(l<q[i].l) Update(a[l++],-1);///如果左端点想去的(q[i].l)在实际(l)的右面,删去最左面的点(少一个点)while(l>q[i].l) Update(a[--l],1);///如果左端点想去的(q[i].l)在实际(l)的左面,往左拓展一个点(多一个点)while(r<q[i].r) Update(a[++r],1);///同理while(r>q[i].r) Update(a[r--],-1);ans[q[i].id]=tmp;///存答案}for(int i=1;i<=m;i++){printf("%d\n",ans[i]);///输出结果}
return 0;
}

带修改莫队

可如果有些问题带修改,怎么办?

带修莫队在原先的二维拓展(l,r)上增加了一个时间维(t),在移动的时候也要移动t使得时间也满足限制

排序方式:左端点所在的块为第一关键字,右端点所在的块为第二关键字,上一个修改操作的时间为第三关键字

剩下的内容就和普通莫队一样了

复杂度玄学 O(n53) O ( n 5 3 ) O(n^{\frac{5}{3}})

题我这个月一定补上!

树莫队

树上莫队其实就是将树化为区间后进行普通莫队

首先弄出一棵树的括号序(入栈时候记一次,出栈时候记一次)

就比如这棵树

括号序是ABCCBDEEFFDA

对每个点记录两次出现的位置(设为 s s s和t" role="presentation">ttt)

对于每组询问 (x,y) ( x , y ) (x,y)(设 x x x比y" role="presentation">yyy深度小):
1.如果两个点在一条链上( x x x是y" role="presentation">yyy祖先),答案为 (x.t,y.t) ( x . t , y . t ) (x.t,y.t)
2.否则,答案为(x.s,y.t)+lca(x,y)

区间内出现两次的节点信息抵消

YY一下发现并没有什么问题,所以是对的(

回滚莫队

有些题维护的信息加一个元素简单删一个难….

就需要回滚莫队

这个我还没写过(我这个月一定写),我看了别人的讲解自己口胡一下

就是设左端点在这个块内的询问,右端点的集合为 S S S,你可以通过处理下一个块最左面的点到S" role="presentation">SSS的答案,再由它向左延伸得到这个块内的答案

没写过,这几天写写,有错误就回来改

根号类算法讲解——各(四)种莫队(填坑)相关推荐

  1. python 类装饰器和继承_python装饰器、继承、元类、mixin,四种給类动态添加类属性和方法的方式(一)...

    介绍装饰器.继承.元类.mixin,四种給类动态添加类属性和方法的方式 有时候需要給类添加额外的东西,有些东西很频繁,每个类都需要,如果不想反复的复制粘贴到每个类,可以动态添加. 1 #coding= ...

  2. python 聚类_聚类算法中的四种距离及其python实现

    欧氏距离 欧式距离也就是欧几里得距离,是最常见也是最简单的一种距离,再n维空间下的公式为: 在python中,可以运用scipy.spatial.distance中的pdist方法来实现,但需要调整其 ...

  3. 基本的排序算法php,php四种基础排序算法

    原标题:php四种基础排序算法 曾经有网友问我关于面试题的问题,今天就发一个面试题笔试经常会出的排序算法,大家可以参考一下,如有问题可以给我留言. /** * php四种基础排序算法的运行时间比较 * ...

  4. 通过@Import注解把类注入容器的四种方式

    文章目录 1. @Import导入的四种方式 2. 准备工作 ①:导入普通类ConfigA ②:导入`@Configuration`配置类ConfigB ③:导入`ImportSelector`的实现 ...

  5. 计算机类和鼠标类是什么关系,四种鼠标类型的优缺点

    四种鼠标类型的优缺点 鼠标的种类有很多,目前常用的鼠标按照定位原理分为光电鼠标.激光鼠标.蓝光鼠标和蓝影鼠标,可能大部分用户并不了解它们之间的区别,只有少数游戏玩家听说过这些鼠标种类.下面就来和小编一 ...

  6. 【算法竞赛学习笔记】莫队算法-超优雅的暴力算法

    title : 莫队算法 tags : ACM,暴力 date : 2021-10-30 author : Linno 普通莫队 常用操作:分块/排序/卡常/离散化等,直接上板子. luoguP270 ...

  7. 【常用算法总结——最短路径四种方法】

    以下转自https://blog.csdn.net/weixin_42060896/article/details/82216379 例题:HDU 2544 最短路 Time Limit: 5000/ ...

  8. 对自定义类实现排序的四种方法

    一.使用LINQ. 二.使用接口IComparable<Product>. 三.使用Sort(Comparison<T> comparison)重载方法. 四.直接使用Orde ...

  9. 神技巧!在Python类初始化时进行四种暗箱操作!

    Python 的类中,所有以双下划线__包起来的方法,叫魔术方法,魔术方法在类或对象的某些事件发出后可以自动执行,让类具有神奇的魔力,比如常见的构造方法__new__.初始化方法__init__.析构 ...

最新文章

  1. LeetCode 316 Remove Duplicate Letters(删除重复字符)
  2. 吴恩达:诸位CEO,我有一本「AI转型秘籍」传授给你
  3. Chipscope使用
  4. (72)Verilog HDL系统函数和任务:$display
  5. mysql 数据备份方案_MySQL常见备份方案
  6. 单龙芯3A3000-7A1000PMON研究学习-(30)撸起袖子干-再来一杯代码11-内存初始化3-mc_init
  7. 大数据与传统数据对比
  8. 关于jupyter notebook闪退问题【我真真的够了,大家以后不要乱捣鼓电脑了,绝了】
  9. rtx3050参数 rtx3050相当于gtx什么显卡 rtx3050显卡什么水平
  10. Mac 蓝牙鼠标卡顿的解决方法
  11. Windows解锁网易云音乐客户端变灰歌曲
  12. Electron Fiddle 通过代理加速下载(Mac)
  13. 《BI工程师必读》数据可视化篇 #02
  14. 蓝桥杯-基础练习 查找整数
  15. android root权限破解分析
  16. 东集PDA连接USB被AndroidStudio识别
  17. 意大利菜--斐波那契汤。具体做法是把昨天的和前天剩下的汤加热后混合,得到就是今天新鲜的“斐波那契汤”
  18. 使用GDI+绘制高质量图和字体
  19. 【转载】SAP_QUERY 使用简介(SQ01,SQVI快速查询报表)
  20. App复杂动画实现——Rive保姆级教程 | 京东云技术团队

热门文章

  1. Python的模块调用
  2. 运用爬虫和分词库统计nga某板块标题词频
  3. 中国全脸头盔市场深度研究分析报告
  4. 地表最强gVim编写Verilog插件 automatic-verilog
  5. 《Decentralized_Privacy_Using_Blockchain-Enabled_Federated_Learning_in_Fog_Computing》精读
  6. 程序员如何进行职业规划---未雨绸缪
  7. c2000 电阻采样_采样电阻选型
  8. RAID磁盘阵列(二)
  9. win7升级旗舰版密钥_电脑如何一键重装系统win7 一键重装win7系统教程
  10. 物联网开发笔记(42)- 使用Micropython开发ESP32开发板之控制蜂鸣器