莫队算法及其应用

秒懂算法 | 莫队算法 本篇介绍了莫队算法的几何意义、基本莫队、带修改莫队以及树上莫队的相关内容。 阅读详情

在写这篇博客之前,我最想做的一件事就是:ORZ莫队%%%%%%%%。

说明:ceil(x)表示x向上取整,sqrt(x)表示对x开算数平方根。

一、莫队算法简介

  莫队算法是一种暴力算法,真的很暴力,但速度很快,属于速度快的暴力。它的基本思想就是分块。关于分块的介绍建议参考hzwer的博客,然后%%%%hzw。莫队算法主要用于解决一类离线查询的问题,和线段树处理的问题是一样的,但处理的是两个不同的方面,当由[L,R]转移到[L’,R’]的时间为O(|L'-L|+|R'-R|)时适宜使用莫队算法。这个可以从题目中体会。因为采取的是分块,它的复杂度是O(nsqrt(n))。其实质是将询问按照某种顺序排好,这个也应该从题目中去体会,我们参考一道题目。

二、典型例题

  著名例题,小Z的袜子

  链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2038

  题目是中文的,看得懂所以不复制粘贴了。题意也不难理解,稍有组合数学常识的人都可以看出。

三、解法

  因为题目中的组合是C(n,2),所以我们预处理出C2数组,存放2-n对2的组合数,作为特例,C(0,2)=C(1,2)=0;

  我们用桶tab存放[L,R]中每种颜色的数量,假设我们求出了[L,R],求[L+1,R](或[L-1,R][L,R+1][L,r-1])时只需要把桶里面的--或++就可以了,令[L,R]的答案为ans,那么[L+1,R]的答案为ans-C(tab[L],2)+C(tab[L]+1,2),这是O(1)的;

  我们可以发现,假设我们求出了[L,R],那么我们求出[L’,R’]的时间为O(|L'-L|+|R'-R|),所以我们采用莫队算法。

  数据范围是n,m<=50000,这启发我们用分块(当然如果执意要写曼哈顿最小生成树那也没人拦你)。我们先将所有询问按照l为第一关键字,r为第二关键字排一遍序,再将排好序的数组分成[√n]块,再将分好块的数组按照r大小排一遍序,这样我们就做完了第一步了。

  接着我们按块处理,对于每一块,找出每个询问和它前面一个询问的差异,修改差异,不断地这么做,就可以得到答案。

  这样做总时间复杂度仅有O(n√n),比原有的O(n^2)的暴力快了许多,但这是为什么呢?

四、复杂度分析

  首先是分块这一步,这一步的时间复杂度毫无疑问地是O(√n*√n*log√n+nlogn)=O(nlogn);

  接着就到了莫队算法的精髓了,下面我们用通俗易懂的初中方法来证明它的时间复杂度是O(n√n);

  证:令每一块中L的最大值为max1,max2,max3,...,maxceil(√n).

  由第一次排序可知,max1<=max2<=...<=maxceil(√n)

  显然,对于每一块暴力求出第一个询问的时间复杂度为O(n)。

  考虑最坏的情况,在每一块中,R的最大值均为n,每次修改操作均要将L由maxi-1修改至maxi或由maxi修改至maxi-1。

  考虑R:因为R在块中已经排好序,所以在同一块修改完它的时间复杂度为O(n)。对于所有块就是O(n√n)。

  重点分析L:因为每一次改变的时间复杂度都是O(maxi-maxi-1)的,所以在同一块中时间复杂度为O(√n*(maxi-maxi-1)).

    将每一块L的时间复杂度合在一起,可以得到对于L的总时间复杂度为

    O(√n*(max1-1)+√n*(max2-max1)+√n*(max3-max2)+...+√n*(maxceil(√n)-maxceil(√n-1)))

      =O(√n*(max1-1+max2-max1+max3-max2+...+maxceil(√n-1)-maxceil(√n-2)+maxceil(√n)-maxceil(√n-1)))

      =O(√n*(maxceil(√n)-1))  (初中裂项求和)

  由题可知maxceil(√n)最大为n,所以L的总时间复杂度最坏情况下为O(n√n).

  综上所述,莫队算法的时间复杂度为O(n√n);

五、例题代码

  还是用emacs写的,所以还是两格缩进,不喜勿喷。

  

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 ll a[60000],tab[60000];
 5 struct ask{
 6   ll l,r,num;
 7 }b[60000];
 8 ll cmp(ask x,ask y){
 9   if(x.l<y.l) return 1;
10   if(x.l>y.l) return 0;
11   if(x.r<y.r) return 1;
12   return 0;
13 }
14 ll comp(ask x,ask y){
15   if(x.r<y.r) return 1;
16   if(x.r>y.r) return 0;
17   if(x.l<y.l) return 1;
18   return 0;
19 }
20 ll gcd(ll a,ll b){
21   if(!b) return a;
22   return gcd(b,a%b);
23 }ll n,m;
24 ll comb2[60000];//组合数C(n,2)
25 ll prix[60000],priy[60000];//答案
26 ll rep(ll ol,ll nl,ll lr,ll nr,ll &ans){//回答修改的问题,原来的是[ol,lr],现在是[nl,nr];
27   if(ol<=nl)
28     for(ll i=ol;i<nl;i++){ans-=comb2[tab[a[i]]]; tab[a[i]]--;ans+=comb2[tab[a[i]]];} 
29   else
30     for(ll i=ol-1;i>=nl;i--){ans-=comb2[tab[a[i]]]; tab[a[i]]++;ans+=comb2[tab[a[i]]];} 
31   for(ll i=lr+1;i<=nr;i++){ans-=comb2[tab[a[i]]]; tab[a[i]]++;ans+=comb2[tab[a[i]]];} 
32   return ans;
33 }
34 
35 int main(){
36   scanf("%lld%lld",&n,&m);comb2[1]=comb2[0]=0;
37   for(ll i=2;i<=n;i++)comb2[i]=(ll)((double)i/2.0*(double)(i-1));//计算组合数
38   for(ll i=1;i<=n;i++) scanf("%lld",&a[i]);
39   for(ll i=1;i<=m;i++){
40     scanf("%lld%lld",&b[i].l,&b[i].r);
41     b[i].num=i;
42   }
43   ll sq=sqrt(m);
44   sort(b+1,b+m+1,cmp);//第一次排序
45   for(ll i=1;i<=m;i+=sq){
46     sort(b+i,b+min(i+sq,m+1),comp);//第二次排序
47   }
48   for(ll i=1;i<=m;i+=sq){
49     ll ed=min(m,i+sq-1);
50     memset(tab,0,sizeof(tab));ll maxx=0;
51     long long ans=0;ans=rep(b[i].l,b[i].l,b[i].l-1,b[i].r,ans);//同下
52     prix[b[i].num]=ans;priy[b[i].num]=comb2[b[i].r-b[i].l+1];//暴力算出每块的第一个,其实这里可以不这么做,直接继承上一块也行
53     if(prix[b[i].num]==0)priy[b[i].num]=1;
54     else{ll g=gcd(prix[b[i].num],priy[b[i].num]);
55       prix[b[i].num]/=g;priy[b[i].num]/=g;}//约分
56     for(ll j=i+1;j<=ed;j++){
57       prix[b[j].num]=rep(b[j-1].l,b[j].l,b[j-1].r,b[j].r,ans);//从上一个询问推导这一个询问
58       priy[b[j].num]=comb2[b[j].r-b[j].l+1];
59       if(prix[b[j].num]==0)priy[b[j].num]=1;
60       else{
61       ll g=gcd(prix[b[j].num],priy[b[j].num]);
62       prix[b[j].num]/=g;priy[b[j].num]/=g;
63       }
64     }
65   }
66   for(ll i=1;i<=m;i++){
67     printf("%lld/%lld\n",prix[i],priy[i]);//这里需要注意,BZOJ有坑,cout是会RE的
68   }
69   return 0;
70 }

 

  

云计算虚拟化实验(一)——虚拟机软件VMware的安装以及虚拟机系统的安装(Windows7+CentOS7) 主要内容: 1、虚拟机软件的安装(以VMware为例) 2、虚拟机系统的安装(Window7 + CentOS7) 3、虚拟主机网络互访 4、不同局域网内的虚拟主机互访(软路由——海蜘蛛) 0 ——首先介绍一下什么是虚拟化? 虚拟化,是指通过虚拟化技术将一台计算机虚拟为多台逻辑计算机。在一台计算机上同时运行多个逻辑计算机,每个逻辑计算机可运行不同的操作系统,并且应用程序都可以在 阅读详情

相关推荐

一文看懂—Agent多智能体协作

多智能体协作已成为AI应对复杂任务的关键范式,通过模拟人类团队分工,实现专业化、高效化和纠错能力。本文系统阐述了多智能体协作的核心概念(智能体分工、工作流编排、工具使用)、与产品规划的关联(任务拆解、错误处理、组织架构设计),以及典型应用场景(报告生成、客服工单、学习规划)。同时剖析了常见陷阱(循环卡死、信息失真、成本失控)及解决方案,并提供了实用工具模板(角色定义卡、工作流画布、成本仪表盘)。最后通过市场竞品分析和旅行规划两个实战案例,展示了多智能体协作的实际价值。该技术正推动AI从单点智能迈向系统智能,

lee006006的博客 1034

【算法】莫队算法

文章目录莫队算法概述:算法过程:时间复杂度:例题:1.洛谷P2709 小B的询问代码思路:完整代码:2.HDU - 6959 zoto题目大意:代码思路:完整代码: 莫队算法概述: 莫队算法是由莫涛发明的算法,所以称为莫队算法。 莫队算法是一个对于区间、树或其他结构离线(在线)维护的算法,此算法基于一些基本算法,例如暴力维护,树状数组,分块,最小曼哈顿距离生成树,对其进行糅合从而产生的算法 其主要用来处理离线的区间问题,如区间和。看到这你会想到线段树,但是他与线段树相比,优点就是可以处理离散的信息,而且代码

Just__Do__IT__的博客 1万+

外贸英文函电第三版张梅英课后习题答案解析

我参加了一些外贸模拟竞赛,将所学知识运用到实际工作中,取得了不错的成绩。此外,我还积极参与了一些外贸实践活动,如参加实习、担任志愿者等,从中积累更多的经验。在这个过程中,我逐渐摸索出了一套适合自己的学习方法,不仅提高了学习效果,还增强了自信心。通过学习这本书,我们可以提高自己在外贸领域的沟通能力,更好地应对未来的工作挑战。在学习这本书的过程中,我遇到了一些困难,比如对某些专业术语的理解不够透彻,对信件的结构和格式掌握不够熟练。出版社: 高等教育出版社。上传者: ʚ河西撒手没ɞ。

weixin_58833001的博客 1426

超全的莫队算法一遍过

莫队的基本思想、回滚莫队、树上莫队、二次离线,一文搞定。什么?你还不会莫队?看完这篇文章你就会了

GROZAX的博客 9016

UE5网络同步优化:GetLifetimeReplicatedProps高级应用指南

本文深入探讨了UE5中GetLifetimeReplicatedProps函数的高级应用与优化策略。文章超越了基础变量注册,重点阐述了如何通过精细的复制条件控制、频率管理及分层复制机制,构建高效的数据同步通道,从而优化网络带宽与游戏性能,是提升多人游戏体验的实用指南。

weixin_29007243的博客 533

kaggle竞赛平台上数据集下载详解

从kaggle 网站上下载数据集既保证了速度又避免了网络的不稳定造成下载失败问题。该平台也可以上传代码作为自己的代码库,不过本人更习惯将代码上传到github上。希望本人整理的kaggle库使用技巧能够帮助到正在阅读本博客的你。此外还有一篇博客针对kaggle数据集下载问题的几个问题的相关文章进行了整理【博客链接】。

li1784506的博客 2万+

详谈莫队算法

本文分别在1、2、3章介绍了普通莫队、带修莫队和回滚莫队算法并详细地分析了最优块长和相对应的时间复杂度。 同时各给出了一道例题的实现。 本文参考了诸多资料,统一置于文末,读者可自行查阅。

Tudou_Pika的博客 3113

华为OD机试双机位C卷-敌情监控 (Py/Java/C/C++/Js/Go)

华为OD机试(机考)双机位C卷 【敌情监控】,提供C语言、Java、C++、Python、Go、JavaScript源码实现,并提供完整思路讲解,以及在线OJ模拟做题。华为OD机试 - 敌情监控。

qq_45776114的博客 938

【技巧】莫队算法

莫队算法通过分块排序查询,离线处理区间统计问题。利用指针移动增量更新答案,适用于可加减的查询,如区间不同数个数,时间复杂度O((n+q)√n)。

zhangmohan123321的博客 1669

YOLOv9改进策略目录 | 包含卷积、主干、检测头、注意力机制、Neck上百种创新机制

Hello,各位读者们好本专栏自开设两个月以来已经更新改进教程50余篇其中包含RepNCSPELAN4、主干、检测头、注意力机制、Neck多种结构上创新,也有损失函数和一些细节点上的创新。同时本人一些讲解视频和包含我所有创新的YOLOv9文档并不能在优快云上传(所有的创新点都经过我的测试是可用的,得到该文件之后大家可以随意组合使用),所以会建立群的形式在内上传我的文件和视频我也会在群内不定期和大家交流回答大家问题,同时定期会更新一些文章的创新点(经过我融合测试后的,先到先得)。

Snu77的博客 1万+

uniapp - 最新微信小程序手机号一键登录功能效果,uniapp小程序实现手机号码一键登录,uniapp微信小程序端通过手机号授权完成立即登录操作(详细示例源码,新手小白一键复制开箱即用)

uniapp,微信小程序,uniapp小程序平台,uniApp手机号一键登录,uniapp小程序端手机号一键登录功能,实现微信小程序手机号一键登录,在uniapp中实现获取手机一键登录功能,uniapp手机号快捷登录,uniapp微信小程序授权登录并获取手机号,微信小程序手机号快速验证组件调用方式,uniapp小程序怎么用手机号一键登录,uniapp一键登录流程及代码,如何获取手机号一键登录到小程序,微信小程序获取本机手机号一键登录功能,新手详细教程,详细手机一键登录完整示例代码,uni-app微信unia

✅ 精选推荐文章 1万+

【优美的暴力】莫队算法

前言 话说为什么莫涛和刘汝佳会研究出这个算法,搞得我这个蒟蒻短暂的OI生涯更加痛苦 但是这个算法真的很优(bao)美(li)。 听说这个算法是莫队(%%%Orz)在集训(做一道毒瘤多次查询题)的时候想出来的。 不管怎么说,%就对了 %%%%% 概念 是什么 在上面已经说过,莫队算法就是前国家队队长( 这等荣耀我们这种蒟蒻只能Orz了! )莫涛(神犇再次%%%)在役时想出来的算法。 莫队算法是用来...

fsy的博客 568

MATLAB基础应用精讲-【深度强化学习】SAC(Soft Actor-Critic)算法(附MATLAB和python代码实现)

Actor 网络:用于选择动作。Critic 1 和 Critic 2 网络:用于估计 Q 值。Target Critic 1 和 Target Critic 2:与 Critic 网络架构相同,用于生成更稳定的目标 Q 值。,即在保证探索的情况下选择高价值动作。软更新目标 Q 网络参数,使得目标网络参数缓慢向当前网络靠近,避免振荡。

qq_36130719的博客 454

莫队算法笔记

莫队算法用于解决不带修改的离线区间问题。 其主要思想是这样的: 先已知区间[L,R]的答案为ans,如果求出区间[L+1,R],[L-1,R],[L,R-1],[L,R+1]的时间均为alpha(),那么就可以在alpha()的时间内转移一个单位区间,求出答案ans’。 因此,我们可以通过安排查询的顺序来使得转移次数尽量少。 可以用平面最小曼哈顿距离生成树来确定查询顺序,不过有一个更好写的方

Quack 1606

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

关于莫队算法的总结

莫队算法是用来骗分的……这个算法的使用前提是 在不强制在线的情况下,对于[l,r],[l',r']的区间询问,我们需要要O(|l-l'|+|r-r'|)次基本操作从[l,r]转移得到[l',r']的答案 可以发现这就是个高能暴力,只不过因为转移方向的优越带来比裸暴力更优的时空复杂度 如果说cdq分治是花费了复杂度干掉了在线,那么莫队就是花费复杂度干掉了区间 对于所有的询问,把当前询问包含的...

weixin_34096182的博客 132

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

莫队算法。

https://blog.youkuaiyun.com/qq_38891827/article/details/82190013很多例题 https://blog.youkuaiyun.com/qq_41117236/article/details/81453534 https://www.lydsy.com/JudgeOnline/problem.php?id=2038 不带修改的莫队。...

denglianna3224的博客 126

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

专题训练之莫队算法

推荐博客/专栏:https://blog.youkuaiyun.com/xianhaoming/article/details/52201761莫队算法讲解(含树上莫队) https://blog.youkuaiyun.com/hzj1054689699/article/details/51866615莫队算法 https://zhuanlan.zhihu.com/p/25017840莫队算法 例题及讲解:(...

weixin_30362233的博客 145

莫队算法学习小记

前言我还是太弱了samjia都打出树上莫队了我还没打过序列上的莫队算法。一定是我对GDKOI2014的题目没有钻研导致我很长一段时间都没有接触莫队算法。 莫队算法可以使用,通常符合以下特点:1、允许离线。2、进行区间询问,并且我们已知区间l~r的答案,可以得到l-1~r或l+1~r或l~r-1或l~r+1这四个区间的答案。3、没有修改操作。序列上的莫队算法莫队算法改变了询问的顺序。 我们对原序列

不来也不去的一只失忆蝴蝶 891

莫队算法

介绍 莫队算法是一个对于区间、树或其他结构离线(在线)维护的算法,此算法基于一些基本算法,例如暴力维护,树状数组,分块,最小曼哈顿距离生成树,对其进行揉合从而产生的一个简单易懂且短小好写的算法。此算法在很多情况下可以很轻松的切掉一些复杂而且难写的数据结构问题。 莫队的门槛 简单的说,莫队算法就是一个优美的暴力算法,假设操作数组的长度为n。在算法中,我们把数组...

weixin_30678821的博客 135

HDU-5213,洛谷-P1494 (莫队算法)

题目链接: 小Z的袜子 思路 莫队算法用于解决离线处理问题,即先把所有询问记录一遍,对询问的进行排序操作后,最终一起输出答案。对于区间询问,其实我们就是设置了两个指针L,R,我们其实可以在O(1)的时间内完成从【L,R】的询问到【L+1,R】或者是【L,R+1】的询问,因此排序的原因就是使得指针跳来跳去的次数能够减少一些。 #include &amp;lt;bits/stdc++.h&amp;gt; usin...

“”云腾致雨“”的博客 225

小Z的袜子(莫队算法)

题目链接 :小Z的袜子 这次比赛有一道题卡了很久,之前以为是Lucas,没想到是莫队算法,早就听说莫队算法对于离线处理时间复杂度一流,这次也算长了见识,这是一道莫队亲手出的莫队算法题,很正规了 挂一个很棒的博客 : 莫队算法学习链接 莫队算法时间复杂度之所以低,是因为提前对数据进行了预处理,使得重复的计算少了很多,值得一提的就是分块,把一个大的区间分成了好多小块。。。这里称之为分块思想,利用...

STOP 262

莫队算法总结

莫队算法 总结 最近两天学习了一下莫队,感觉莫队算法还是挺好用的(现在看到离线询问就想莫队... 就稍微写一下总结吧,加深一下对算法的理解。 普通莫队 核心思想:莫队算法一般用来离线处理一系列无修改的区间询问问题,通过将所有的询问保存下来,并且将所有的询问区间进行适当地排序,从而达到降低时间复杂度的效果。 对于所有的询问区间\([l_i,r_i]\),如果暴力地进行区间端点移动,那么...

dft539533的博客 214

莫队算法入门 Codeforces617E

莫队算法: 莫队算法的用处是,对于一个区间内的查询,当我们已经知道了 [ L , R ] 的答案的时候,有莫队算法可以在很短的时间内得到 [ L - 1 , R ] 或者是 [ L ,R + 1 ]的答案,前提是可以离线处理。 步骤: 1.输入 N 个点的时候,对每个点的进行分块 ,一般 N 个点分成 sqrt(n) 块 ,用一个pos[]数组记录分块 int s = sqrt(n); f

LinzhiQQQ的博客 637
上一篇: quagga源码学习--BGP协议对等体连接tcp md5签名认证选项
下一篇: mysql安装方法
ppf19159
博客等级 码龄11年 15粉丝 56原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值