莫队算法(普通莫队、带修莫队、树上莫队、不删除莫队)学习笔记【理解+套路/核心代码+例题及题解】

article/2025/10/24 4:33:03

一、理解

我的理解就是巧妙的暴力,利用双指针以及分块思想,巧妙的移动双指针,时间复杂度可以达到O(NlogN)

强推博客:写的又好又全。链接

二、套路

1、普通莫队

【1】核心代码

bool cmp(node a,node b){return belong[a.l]==belong[b.l]? a.r<b.r:belong[a.l]<belong[b.l];
}	
sort(q+1,q+1+m,cmp);
int l=1,r=0;
for(int i=1;i<=m;i++){int ql=q[i].l,qr=q[i].r;while(l<ql) del(l++);while(l>ql) add(--l);while(r<qr) add(++r);while(r>qr) del(r--);	ans[q[i].id]=cnt;
}

add和del函数随机应变,一般都是加入或删除一个数对答案的影响。证明一下复杂度吧,便于理解代码。

(1)对左指针L,假设一个块内有x个询问,每次L最多移动\sqrt{n}次,加起来为O(\sum{x\sqrt{n}}) = O(m\sqrt{n});对于不同块之间的L,跨越一个块L最多移动\sqrt{n}次,总共可能跨n次,为O(n\sqrt{n}})

(2)对于右指针R,对于不同块之间的R,它是无序的,最多移动n次,有\sqrt{n}块,为O(n\sqrt{n});块内的R有序,R最多移动\sqrt{n}次,总共\sqrt{n}块,为O(n)

因此总体为max( O(m\sqrt{n}) , O(n\sqrt{n})),有常数。

【2】例题及题解(从易到难)

(1)luogu SP3267 DQUERY - D-query      题解

(2)luogu P1972 [SDOI2009]HH的项链      题解

(3)luogu P2709 小B的询问      题解      

(4) CodeForces - 86D Powerful array      题解

(5)luogu P1494 [国家集训队]小Z的袜子      题解 

(6)luogu P3709 大爷的字符串题       题解

(7)CodeForces - 617E XOR and Favorite Number      题解

2、带修莫队

【1】核心代码

bool cmp(node a,node b){return (be[a.l]^be[b.l])?be[a.l]<be[b.l] :(be[a.r]^be[b.r]) ? be[a.r]<be[b.r] : a.tim<b.tim;
}
blcok=ceil(pow(1.0*n,2.0/3.0));//注意这里要变为n^(2/3) 
int l=1,r=0,ti=0;
while(l<ql) del(l++);
while(l>ql) add(--l);
while(r<qr) add(++r);
while(r>qr) del(r--);
while(ti<qt){++ti;if(ql<=b[ti].pos&&b[ti].pos<=qr)del(b[ti].pos);swap(a[b[ti].pos],b[ti].col);if(ql<=b[ti].pos&&b[ti].pos<=qr)add(b[ti].pos);
}
while(ti>qt){if(ql<=b[ti].pos&&b[ti].pos<=qr)del(b[ti].pos);swap(a[b[ti].pos],b[ti].col);if(ql<=b[ti].pos&&b[ti].pos<=qr)add(b[ti].pos);--ti;
}

对于带修莫队,我们需要给每一个询问加一个时间戳,时间戳的取值就是之前最近的修改。排序时,先按左边界的块,再按右边界的块,最后按时间戳。先移动左右指针,然后再考虑修改

如果时间戳大了,说明我们改多了,我们需要再改回去改的时候,要考虑是否对答案造成影响

如果时间戳小了,说明我们改少了,要改到询问所在的时间戳,改的时候,要考虑是否对答案造成影响

使用swap可以方便地进行修改。(具体看上面代码)

注意:有的dalaodalao证明了当块的大小设n^{\frac{3}{4}}时理论复杂度达到最优。不过可以证明,块大小取n^{\frac{2}{3}}优于取\sqrt{n}的情况,总体复杂度O(n^{\frac{5}{3}})。而块大小取\sqrt{n}时会退化成O(n^{2}),不建议使用。(出处

【2】例题及题解

(1)luogu P1903 [国家集训队]数颜色 / 维护队列     题解

(2)HDU - 6610 Game      题解

(3)luogu P4074 [WC2013]糖果公园 【树上带修莫队有难度】      题解

3、树上莫队

【1】核心代码

bool cmp(Node a,Node b){return (be[a.l]^be[b.l]) ? be[a.l]<be[b.l] : (be[a.l]&1) ? a.r<b.r : a.r>b.r;
}
int fir[N],la[N],dfn[N<<1],tot=0;
int dep[N],f[N][30]; 
void dfs(int u,int fa){fir[u]=++tot;dfn[tot]=u;for(int i=1;i<=20;++i)f[u][i]=f[f[u][i-1]][i-1];for(int i=head[u];~i;i=g[i].nex){int v=g[i].to;if(dep[v]||v==fa) continue;dep[v]=dep[u]+1;f[v][0]=u;dfs(v,u);}la[u]=++tot;dfn[tot]=u;
}
int getLca(int x,int y){if(dep[x]<dep[y]) swap(x,y);int dis=dep[x]-dep[y];for(int i=20;i>=0;--i)if(dis&(1<<i))x=f[x][i];if(x==y) return x;for(int i=20;i>=0;--i)if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i]; return f[x][0];
}
void change(int x){x=dfn[x];vis[x] ? del(x) : add(x);vis[x]^=1;
}
for(int i=1;i<=m;++i){int u,v;//scanf("%d%d",&u,&v);u=read(),v=read();if(fir[u]>fir[v]) swap(u,v);int lca=getLca(u,v);if(lca==u)q[i].l=fir[u];elseq[i].l=la[u],q[i].lca=lca;;q[i].r=fir[v];q[i].id=i;
}	
sort(q+1,q+1+m,cmp);
int l=1,r=0;
for(int i=1;i<=m;i++){int ql=q[i].l,qr=q[i].r,lca=q[i].lca;	while(l<ql) change(l++);while(l>ql) change(--l);while(r<qr) change(++r);while(r>qr) change(r--);ans[q[i].id]=sum;if(lca && !num[a[lca]]) ++ans[q[i].id];		
}

这里需要了解欧拉序(强推博客),利用欧拉序,就可以把树上的路径转化为连续区间的问题。

这里还要求lca。对于树上u到v的路径,设first[u]<first[v],

如果lca(u,v)==u,对应欧拉序的连续区间就为[ first[u] , first[v] ] ;

否则, 对应欧拉序的连续区间就为[ last[u] , first[v] ] , 不过还要加上 lca(u,v)

要注意的是区间中出现两次的点并不在u到v的路径中,所以我们需要一个vis数组,每次进行异或操作。根据vis[i],进行删除操作/添加操作。

一定记得有的数组需要开2*n并且别忘了加lca的贡献 !!!!!!!!

【2】例题及题解

(1)luogu SP10707 COT2 - Count on a tree II​​​​​​​      题解

(2)luogu P4074 [WC2013]糖果公园​​​​​​​ 【树上带修莫队有难度】     题解

4、不删除莫队

【1】核心代码

bool cmp(node a,node b){return (be[a.l]^be[b.l]) ? be[a.l]<be[b.l] : a.r<b.r;
}
block=ceil(sqrt(1.0*n));
bnum=ceil(1.0*n/block);
for(int i=1;i<=bnum;i++){bl[i]=br[i-1]+1,br[i]=br[i-1]+block;for(int j=bl[i];j<=br[i];j++)be[j]=i;
}
for(int i=1;i<=m;i++)scanf("%d%d",&q[i].l,&q[i].r),q[i].id=i;
sort(q+1,q+1+m,cmp);
int pos=1;
ll sum;
for(int i=0;i<=bnum;i++){sum=0;memset(cnt,0,sizeof cnt);int l=br[i]+1,r=br[i];for(;be[q[pos].l]==i;pos++){int ql=q[pos].l,qr=q[pos].r;if(be[ql]==be[qr]){ll temp=0;for(int j=ql;j<=qr;j++) cnt1[mp[a[j]]]=0;for(int j=ql;j<=qr;j++){++cnt1[mp[a[j]]];temp=max(1LL*a[j]*cnt1[mp[a[j]]],temp) ;}ans[q[pos].id]=temp;				continue;}while(r<qr){++r;++cnt[mp[a[r]]];sum=max(sum,1LL*a[r]*cnt[mp[a[r]]]); }ll temp=sum;while(l>ql){--l;++cnt[mp[a[l]]];sum=max(sum,1LL*a[l]*cnt[mp[a[l]]]); 				}ans[q[pos].id]=sum;while(l<br[i]+1){--cnt[mp[a[l]]];l++;}sum=temp;}
}

对于普通莫队,我们一般考虑添加和删除只是顺序变一下,但有的题删除操作根本没办法维护需要的东西。

这时,不删除莫队就可以大显神威了,删除太难了,那我们不删除,只添加就好了。

现在考虑怎么不删除,我们排序时,对于左端点在同一个块内的询问他们的r是从小到大有序的,那么我们可以利用这个特点,一个块一个块的计算询问区间

对于左端点在同一个块内的询问:

首先考虑,如果询问区间的左右端点(ql、qr)都在一个块内,那我们直接暴力计算,复杂度为O(\sqrt{n}),最多m个询问区间的左右端点(ql、qr)都在一个块内,复杂度为O(m\sqrt{n})

否则,我们保持r有序,那么对于左端点一个块内的询问,r最坏从头到尾遍历一遍为O(n),总共\sqrt{n}块,复杂度也为O(n\sqrt{n})

对于每个询问,我们现在只要移动l即可,l最多移动\sqrt{n}次,最多m个询问区间,O(m\sqrt{n})

总体复杂度max( O(m\sqrt{n}) , O(n\sqrt{n}))

对于块i中的询问,将l和r初值置为l=br[i]+1,r=br[i]即可。

注意,对于l移动时,带来的修改只对当前询问有关,所以改了要再改回去,有时还要维护两组状态

注意,这里还有个块0需要带着。

【2】例题及题解

(1)luogu AT1219 歴史の研究​​​​​​​     题解

(2)luogu SP3267 DQUERY - D-query      题解

(3)luogu P5906 【模板】回滚莫队&不删除莫队​​​​​​​      题解

三、最后一题

树上带修莫队,检验一下自己吧。

luogu P4074 [WC2013]糖果公园​​​​​​​      题解

 

参考且强推博客:https://www.cnblogs.com/WAMonster/p/10118934.html

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


http://chatgpt.dhexx.cn/article/4fvaSOhv.shtml

相关文章

香港理工大学计算机系石杰明老师组招收全奖博士生、博士后

来源&#xff1a;AI求职 香港理工大学 香港理工大学位于中国香港特别行政区&#xff0c;QS 最新排名世界 66 位。计算机系&#xff08;Department of Computing&#xff09;USNews CS 排名 36&#xff0c;泰晤士 CS 排名 79。 石杰明博士课题组成员包括有 985/211 顶尖高校背景…

【调剂】华侨大学计算机学院计算机视觉与模式识别实验室钟必能课题组研究生招生...

点击文末的阅读原文或者公众号界面左下角的调剂信息或者公众号回复“调剂”是计算机/软件等专业的所有调剂信息集合&#xff0c;会一直更新的。 课题组主页&#xff1a;https://cst.hqu.edu.cn/info/1109/2001.htmLinkedin: https://www.linkedin.com/in/bineng-zhong-71a36674…

莫队算法思想

目录 莫队算法普通莫队方法&#xff1a;主要代码结构&#xff1a;例题&#xff1a;小B的询问例题&#xff1a;小Z的袜子奇偶化排序 带修改的莫队小结&#xff1a; 莫队算法 莫队算法是由前国家队莫涛提出的一种算法&#xff0c;主要应用在一类离线区间查询的问题中&#xff0c…

【华人学者风采】冯佳时 新加坡国立大学

【华人学者风采】冯佳时&#xff0c;新加坡国立大学ECE系助理教授。本科毕业于中国科学技术大学&#xff0c;硕士毕业于中国科学院自动化研究所&#xff0c;博士毕业于新加坡国立大学。研究兴趣包括大污染数据分析&#xff0c;在线和分布式鲁棒性学习及其在对象识别中的应用。 …

港科夜闻|央视网专访香港科大(广州)(筹)校长倪明选教授,谈香港科技大学在科研及知识转移方面成就...

关注并星标 每周阅读港科夜闻 建立新视野 开启新思维 1、央视网专访香港科大(广州)(筹)校长倪明选教授&#xff0c;谈香港科技大学在科研及知识转移方面成就。香港科技大学(广州)(筹)校长倪明选教授接受央视网专访&#xff0c;谈香港科技大学在科研及知识转移方面取得的成就&am…

独家对话许诗军:数字化转型,最基本的是不去拒绝 |数字价值观察室(下)...

关注ITValue&#xff0c;看企业级最新鲜、最价值报道&#xff01; ▎本文摘自《云栖战略参考》&#xff0c;这本刊物由阿里云与钛媒体联合策划。目的是为了把各个行业先行者的技术探索、业务实践呈现出来&#xff0c;与思考同样问题的“数字先行者”共同探讨、碰撞&#xff0c;…

港科夜闻|香港科技大学(广州)(筹)校长倪明选教授在北京拜访国家教育部党组书记、部长怀进鹏...

关注并星标 每周阅读港科夜闻 建立新视野 开启新思维 1、香港科技大学(广州)(筹)校长倪明选教授在北京拜访国家教育部党组书记、部长怀进鹏。2021年11月1日&#xff0c;香港科技大学(广州)(筹)校长倪明选教授等一行在北京拜访国家教育部党组书记、部长怀进鹏。 2、深圳先进院与…

特么的. 最终把 amobbs 的站长阿莫(莫进明)给回骂了一顿.

起因: 假设你居住的地方&#xff0c;要上马PX等高污染的项目&#xff0c;你会怎么做. 鼓动别人上街暴力示威与军警对抗. 自己待在家里支持怂恿. 这样的人真心猥琐! 鉴于他常常私自改动帖子, 在此截图留存. 真特么没劲. 居然以封锁别人 ID 作为别人"打不还手骂不还口…

中国计算机专业创始人,无怨无悔来时路――访计算机专业创始人吴忠明校友

哈工大报讯(研究生记者团杜&#xfffd;/文 李贵才/图)&#xff15;&#xff10;年前&#xff0c;他和他的同事创建了中国最早的计算机专业之一――哈工大计算机专业。从此&#xff0c;“哈工大计算机”作为哈工大的一张名片&#xff0c;&#xff15;&#xff10;载享誉海内外。…

史上首次,45岁计算机大牛蒋濛当选普渡大学校长!

作者丨编辑部 来源丨新智元 【导读】普渡大学史上首位华裔校长诞生&#xff01;45岁计算机大牛蒋濛当选&#xff0c;本硕博全藤校&#xff0c;产学研大满贯的他&#xff0c;此前曾屡拒其他名校。 刚刚&#xff0c;年仅45岁的华裔科学家蒋濛被任命为美国普渡大学第13任校长。 这…

港科夜闻|香港科技大学(广州)倪明选校长一行到访广东省科学技术厅,与龚国平厅长、吴世文副厅长参加交流座谈会议...

关注并星标 每周阅读港科夜闻 建立新视野 开启新思维 1、7月21日&#xff0c;香港科技大学&#xff08;广州&#xff09;倪明选校长一行到访广东省科学技术厅&#xff0c;与龚国平厅长、吴世文副厅长参加交流座谈会议。座谈会上&#xff0c;倪明选校长介绍了香港科大&#xff0…

apktool反编译apk教程

1.准备工具 (1)apktool的下载地址:https://bitbucket.org/iBotPeaches/apktool/downloads/ 点击超链接下载最新版本 (2)apktool.bat:将下面的脚本复制到文本并保存&#xff0c;然后重命名为apktool.bat; echo off setlocal set BASENAMEapktool_ chcp 65001 2>nul >nul…

C#反编译工具Reflector.exe教程

reflector.exe是一款专业的.NET反编译软件。reflector.exe可以分析程序集并向你展示它的所有秘密。.NET 框架向全世界引入了可用来分析任何基于 .NET 的代码(无论它是单个类还是完整的程序集)的反射概念。反射还可以用来检索有关特定程序集中包含的各种类、方法和属性的信息。 …

java反编译超简单教程

第一步&#xff1a;这里是代码编译完输出.class的路径&#xff0c;有自己想要反编译的程序可以跳过这一步 第二步&#xff1a;看好路径&#xff0c;将想要反编译的class文件&#xff0c;拖到src.....main...最后的项目文件夹中 完成&#xff1a;发现dog文件已经加载在我们项目中…

android反编译修改教程,逆向教程之-反编译apk修改菜单默认设置(一)

本帖最后由 liuxiaoxin 于 2020-12-3 18:58 编辑 授人以鱼,不如授人以渔!本教程图文并茂,步骤非常详细,偏小白向,大佬请自觉屏蔽。 使用工具:MT管理器免费版 被修改的软件:Apktool M_v2.4.1 如果想跟着教程一起实操,感受一下反编译带来的乐趣,修改成功之后油然而生的成…

新Android反编译教程

今天百度搜索“Android反编译”搜索出来的结果大多数都是比较传统的教程。刚接触反编译的时候&#xff0c;我也是从这些教程慢慢学起的。在后来的学习过程中&#xff0c;我接触到比较方便操作的Android反编译。在这&#xff0c;我将使用的过程写下来&#xff0c;贡献给有需的朋…

小龟视频APP-插件打包-v1.6.x反编译教程及未加固apk包ios最新版文件分享

1.先爆破安卓签名&#xff0c;工具&#xff1a;MT管理器&#xff0c;百度自行下载 2.搜索getcertsign&#xff08;一般在285之间都能看到&#xff09;如下图&#xff1a; 3.添加return-void 然后保存返回回到首页进行APK签名&#xff0c;就ok了 这样就爆破好了把这里修改成你自…

springboot项目代码混淆和反编译教程·附软件连接

对springboot项目进行代码混淆&#xff0c;可以防止别人通过反编译项目查看代码&#xff0c;即使反编译了查看的也是混淆后的看不懂的代码。 一定程度保证了项目源码安全性。 下面分享代码混淆步骤和反编译操作 Allatori-7.7 代码混淆操作步骤 使用方法 1、首先从官网下载&a…

一键反编译Android包教程

2023.6.6更新&#xff1a; 因为引入了v2签名&#xff0c;所以工具包进行了更新&#xff0c;已经支持v1 v2签名&#xff0c;签名工具替换为apksigner.jar 功能介绍 某些时候我们想修改apk包内容&#xff0c;比如汉化某个游戏&#xff0c;这时候就需要修改游戏apk的包内容&…

ApkToolkit 反编译 教程

今天踩了一遍坑&#xff0c;算是成功了&#xff0c;坑就不描述了&#xff0c;按如下方法应该可以OK完成反编译再打包签名。 使用工具ApkToolkit 第一步&#xff1a;下载ApkToolkit并解压&#xff0c;随便丢哪儿都行 下载地址&#xff1a;https://down.52pojie.cn/Tools/Android…